Main은 size만 조정하겠습니다.


Scene scene = new Scene(root,200,200);





fxml을 열어 캡처와 같이 수정


BorderPane Center 위에 AnchorPane


그 위에 Button, Code 부분은 캡쳐와 같이 설정


그리고 나서 fxml을 이름만 custom으로 설정해 새로 만들어서




AnchorPane 위에


Button - Code : fx:id - closebtn


    On Action - close


Label - Code : fx:id - label


위와 같이 추가하고 저장, 닫기 기능을 구현하기 때문에 Controller class 등록을 해준다.


이번에는 컨트롤러 클래스에서 방법 2를 이용해 스테이지를 불러오고


새로운 스테이지를 생성해서 그 위에 팝업을 띄우는 작업을 한다.



package app;

import java.io.IOException;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class MainController {
	@FXML private Button btn;
	@FXML private Button closebtn;
	@FXML private Label label;

	private Stage pop; // 스테이지가 들어갈 변수
	
	public void popup() {
		// 메인 스테이지 취득, 전의 두가지 방법 중 두번째 방법
		Stage mainStage = (Stage)btn.getScene().getWindow(); 
		
		// 새로운 스테이지 생성 (옵션 추가, 스타일)
		Stage pop = new Stage(StageStyle.DECORATED); // 스테이지 옵션
		pop.initModality(Modality.WINDOW_MODAL); // 그 위에 뜨는 모달의 옵션
		pop.initOwner(mainStage); // 메인 스테이지 부여
		
		try {
			// 새로운 스테이지에 custom 레이아웃 불러오기
			Parent root = FXMLLoader.load(getClass().getResource("custom.fxml"));
			
			// 씬에 추가
			Scene sc = new Scene(root);
			pop.setScene(sc);
			pop.setTitle("팝업 띄우기");
			pop.setResizable(false); // 창 사이즈 조절 차단
			
			// 보여주기
			pop.show();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void close() { // 현재의 스테이지를 받아서 close를 해주어야 함
		pop = (Stage)closebtn.getScene().getWindow(); // 버튼을 통해서 현재 스테이지를 알아냄
		pop.close();
	}
}




팝업창을 새로 띄우기 위해서는 여태껏 별로 건들지 않았던 Main을 수정해야 한다.


BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("main.fxml"));


기존의 BorderPane인데 이것을 주석 처리하고 다음 코드처럼 추가해준다.


package app;
	
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;


public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
//			BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("main.fxml"));
//			FXMLLoader.load() <- static, 복사 ㄴㄴ
			// 기존 방식과 다르게 instance 방식을 사용, 복사 가능, 복수의 화면 사용이 가능해진다.
			// 여기부터
			FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
			BorderPane root = loader.load();
			
			/* Stage 취득방법1 (화면제어방법) - Controller에 Stage 전달
			MainController con = loader.getController();
			con.setStage(primaryStage);
			*/
			
			// 여기까지 추가
			
			Scene scene = new Scene(root,200,200); // 창 크기는 마음대로
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}



다음으로는 main.fxml을 씬 빌더로 열어 다음과 같이 수정한다.


Stage를 받는 방법이 두가지가 있는데 주석 부분을 통해서 확인해보자. (2번째 방법은 Controller 클래스에서)


다음으로 씬 빌더를 열어 fxml 파일을 수정하자







Border Pane Center에 Pane을 올리고


버튼 하나 추가


버튼의 코드는 사진과 같이 설정





이번에는 FXML 파일을 하나 더 추가하여 그걸 팝업으로 띄운다.


추가하는 방법은 다음과 같다.





사진 순서대로 따라서 진행하고 


마지막 화면에서


Source folder는 저장될 경로


Package는 소스 폴더 안의 파일을 만들 패키지


Name은 파일 이름


Root Element는 디자인 할 때 어떤 Pane을 사용할건지 정한다.


Dynamic Root는 생략


Finish를 눌러 생성하고 Scene Builder로 열어서 수정 (필자는 popup이라고 이름을 설정)






popup.fxml을 다음과 같이 배치


HBox - Layout size pref 를 200, 40


Label - Layout size pref 를 200, 40


  - Properties를 아래로 내리면 CSS를 수정할 수 있는데 첫번째 스타일을 캡쳐와 같이 수정


컨트롤러 클래스는 따로 기능을 넣지 않으므로 설정하지 않아도 된다.


원래 CSS는 다루지 않지만 이번에만 색깔 입히는식으로 해보자.


다음으로는 처음 수정한 fxml 파일의 컨트롤러 클래스이다.


컨트롤러에서는 버튼을 눌렀을때 팝업창이 뜨게끔 하고 다른 곳을 눌렀을때 사라지는 설정을 추가한다.


특히 Stage의 정보를 얻는 방법 2번째가 나오니 주의깊게 보자.



package app;

import java.io.IOException;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.stage.Popup;
import javafx.stage.Stage;

public class MainController {
	private Stage Stage;
	@FXML private Button btn;
	
	/* Main에서 Stage 가져오는 방법
	public void setStage(Stage Stage) {
		this.Stage = Stage;
	}
	*/
	
	public void popUp() {
		/* Stage 취득방법2 - Control로 부터 소속 스테이지 취득
		 * 여기서는 버튼을 통해서
		 */
		Stage = (Stage)btn.getScene().getWindow();
		
		
		// 팝업 객체
		Popup pop = new Popup(); // 투명한 틀을 하나 선언한다고 이해하면 된다.
		
		// 레이아웃 생성(팝업)
		try {
			// 아래 코드를 입력하면 try catch문이 필요하다고 나온다.
			Parent root = FXMLLoader.load(getClass().getResource("popup.fxml")); // 저번에 설명한 경로 땡겨오기
			
			// 팝업 객체에 레이아웃 추가
			pop.getContent().add(root);
			pop.setAutoHide(true); // 포커스 이동시 창 숨김
			
			// 팝업 객체에서 스테이지를 보여줌
			pop.show(Stage);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}
}




'JavaFX > 01.Node 추가' 카테고리의 다른 글

[JAVA FX]01-18.여러가지 레이아웃 전환 방법  (2) 2018.09.12
[JAVA FX]01-17.Popup 띄우기2 (방법2)  (0) 2018.09.12
[JAVA FX]01-15.AudioPlayer  (0) 2018.09.12
[JAVA FX]01-14.Media Player  (0) 2018.09.11
[JAVA FX]01-13.BarChart  (0) 2018.09.11

이번에는 음악 플레이어를 만들기 때문에 크기를 조금 줄인다.


Main의 


Scene scene = new Scene(root,400,200);


400, 200 으로 수정




BorderPane Center 부분에 Pane을 올려 사용


Slider - Code : fx:id - seekBar


MediaView - Code : fx:id - mediaView  (모습이 드러나지 않는 노드이기 때문에 아무대나 배치하면 된다.)


Label - Code : fx:id - playList


Label - Code : fx:id - playTime


Button - Code : On Action - open


Button - Code : On Action - play


Button - Code : On Action - pause


Button - Code : On Action - fast


Button - Code : On Action - slow


Button - Code : On Action - start


Button - Code : On Action - last



이번에 만들 Audio Player는 전과 같이 MediaView를 사용하지만 mediaview는 재생하여 소리를 나게 하기 위한 ui로 


따로 모습이 필요없다.


고로 아무대나 배치하면 되고 각 버튼을 통해서 선택한 음악의 재생관리를 구현한다.


특별한것은 예전에 배웠던 split이나 (long)과 같은 명시적 형변환 등 쓰이는게 많다.


그리고 버튼 play에 거의 모든 기능이 쓰이므로 play 함수를 유심히 보자.



package app;

import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class MainController implements Initializable{

	@FXML private Slider seekBar;
	@FXML private Label playList;
	@FXML private Label playTime;
	@FXML private MediaView mediaView;
	Media media;
	MediaPlayer player;

	String mediaPath;
	long totalTime, currentTime;

	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML 완");
		seekBar.setValueChanging(true); // 외부에서 슬라이더바 조작 가능
		seekBar.setValue(0);
	}

	public void open() {
		FileChooser fc = new FileChooser();
		fc.setTitle("음악 파일 선택");
		fc.setInitialDirectory(new File("C:/")); // 기본 경로
		// 확장자 필터링(선택)
		ExtensionFilter filter = new ExtensionFilter("audio", "*.mp3");
		fc.getExtensionFilters().add(filter);


		File selectedFile = fc.showOpenDialog(null); // 창 위치 및 불러운 파일 삽입
		mediaPath = selectedFile.toURI().toString();
		System.out.println("선택한 경로 : " + mediaPath);

		// playList에 재생할 파일명 출력
		String[] token = mediaPath.split("/");
		// 공백의 경우 %20으로 표시되어 공백으로 바꿔주고 넣는다.
		String musicName = token[token.length-1].replaceAll("%20",  " ");
		// 리스트에 삽입
		playList.setText(musicName);

		// 미디어 등록 - 플레이어 등록 - 뷰에 등록
		media = new Media(mediaPath);
		player = new MediaPlayer(media);
		player.setAutoPlay(false); // 자동실행 false, play 버튼을 누를 시 음악이 재생되게끔
		mediaView = new MediaView(player);
	}

	public void play() {
		currentTime = 0;
		totalTime = 0;
		player.play();
		player.setRate(1); // 재생속도 기본 (1), 디폴트값
		totalTime = (long) player.getTotalDuration().toSeconds(); // 노래가 몇초짜리인지 반환
		System.out.println(totalTime);

		// 슬라이더를 움직이기 위한 스레드 생성
		// 스레드가 별개로 돌아가기 때문에 재생하고 창을 종료하면 계속 재생되는 상태이다.
		Thread th = new Thread(()-> {
			while(currentTime < totalTime) { // 재생시간에 따라 스레드 종료
				currentTime = (long)player.getCurrentTime().toSeconds();
				Platform.runLater(()->{
					seekBar.setValue((double)currentTime/totalTime*100);
					playTime.setText(currentTime + "/" + totalTime);
				});
				// sleep 0.3초를 주어서 좀 더 안정감있게 slidebar를 제어
				// 없다면 계산이 너무 빠르기 때문에 불안정
				try {
					Thread.sleep(300);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} 
			}
			player.stop();
		});
		th.start();
	}

	public void pause() {
		player.pause();
	}

	public void fast() { // 0.5배 빠르거나 느리게, 숫자를 변수로 받아 선언하여 활용 가능 
		player.setRate(1.5);
	}

	public void slow() {
		player.setRate(0.5);
	}

	public void start() { // 첫 시간대로 이동
		player.seek(player.getStartTime());
	}

	public void last() { // 마지막 시간대로 이동
		player.seek(player.getTotalDuration());
	}

}












token[token.length-1].replaceAll("%20",  " ");


위의 코드에 replaceAll을 사용하지 않으면 띄어쓰기가 %20처럼 이상하게 출력되는것을 방지 할 수 있다.




슬라이더를 통해서 조절하는 여러가지 기능은 직접 만들어보시길... 어렵지않다.









'JavaFX > 01.Node 추가' 카테고리의 다른 글

[JAVA FX]01-17.Popup 띄우기2 (방법2)  (0) 2018.09.12
[JAVA FX]01-16.Popup 띄우기 (방법 1,2)  (0) 2018.09.12
[JAVA FX]01-14.Media Player  (0) 2018.09.11
[JAVA FX]01-13.BarChart  (0) 2018.09.11
[JAVA FX]01-12.Line Chart, Random  (0) 2018.09.11

+ Recent posts