-
javaFX - 다이얼로그카테고리 없음 2020. 5. 23. 12:20
javaFX 다이얼로그
다이얼로그 : 주 윈도우에서 알림이나 사용자의 입력을 위해 실행되는 서브 윈도우.
자체적으로 실행될 수 없음. 주 윈도우(소유자 윈도우)에서 띄워준다.
모달 과 모달리스 두 가지 종류가 있음.
모달 다이얼로그 : 다이얼로그를 닫기 전까지 소유자 윈도우 사용불가.
모달리스 다이얼로그 : 소유자 윈도우 계속 사용가능.
다이얼로그 종류
1. FileChooser : 파일 선택
2. DirectoryChooser : 디렉토리 선택
3. popup : 팝업창
FileChooser
로컬 PC의 파일을 선택할 수 있는 다이얼로그.
열기, 저장을 할 수 있음. 파일 확장명을 필터링하여 원하는 파일만 볼 수도 있음.
컨트롤이 아니다 => FXML에서 선언 X
버튼이나 메뉴 아이템의 ActionEvent를 처리할 때 자바 코드로 FileChooser를 생성하고,
showOpenDialog() or showSaveDialog()를 호출해야 함.
사용방법 FileChooser fc = new FileChooser(); fc.getExtensionFilters().addAll( new ExtemsionFilter(), new ExtemsionFilter(), // 파일 확장자 명으로 필터링. new ExtemsionFilter(), new ExtemsionFilter()); File selectedFile = fc.showOpenDialog(primaryStage); // 다이얼로그 띄움. String selectedFilePath = selectedFile.getPath(); // 선택된 파일의 경로.
fileChooser는 모달 다이얼로그이므로
showOpenDialog() or showSaveDialog()를 호출할 때는 소유자 윈도우(Stage)를 매개값으로 해야함.
DirectoryChooser
파일이 아니라 Directory(폴더)를 선택할 때는, FileChooser 대신 DirectoryChooser를 사용.
DirectoryChooser dc = new DirectoryChooser(); File selectedDc = dc.showDialog(primaryStage); String selectedDcPath = selectedDc.getPath();
pop
투명한 컨테이너를 제공하는 모달리스 다이얼로그=> 소유자 윈도우에서 계속 사용 가능.
컨트롤의 tooltip, 메세지 통지, 드롭다운 박스, 마우스 오른쪽 클릭했을 때 나타나는 메뉴 등등을
만들 때 사용될 수 있음.
ex)메세지 통지 popup Popup pu = new Popup(); pu.getContent().add(FXMLLoader.load(getClass().getResource("popup.fxml"))); show() : popup 실행 메서드. pu.show(primaryStage); // 화면 정중앙에 실행. pu.show(primaryStage, anchorX, anchorY); // 지정된 좌표에서 실행.
Popup은 다른 윈도우보다 최상위 위치에 놓임
=> Popup이 실행되면 어떤 윈도우를 실행해요 Popup이 항상 제일 위에 옴.
Popup을 닫으려면??
=> 주 윈도우를 닫거나, Popup에 추가된 컨트롤 이벤트를 처리하여 hide()메서드 호출.
가장 간단 방법: setAutoHide(true)를 설정하는 방법.
pu.setAutoHide(true); / 포커스가 다른 윈도우로 이동하면 Popup은 자동으로 닫힘.
예제) 메세지 통지용 Popup 예제 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.*?> <?import java.lang.*?> <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <?import javafx.scene.layout.*?> <HBox xmlns:fx="http://javafx.com/fxml" alignment="CENTER_LEFT" style="-fx-background-color: black; -fx-background-radius: 20;" > /CSS 적용. <children> <ImageView id="imgMessage" fitHeight="30" fitWidth="30" preserveRatio="true"/> <Label id="lblMessage" style="-fx-text-fill: white;"> /CSS 적용. <HBox.margin> <Insets left="5.0" right="5.0" /> </HBox.margin> </Label> </children> </HBox> Popup 실행 코드. Popup pu = new Popup(); Parent parent = FXMLLoader.load(getClass().getResource("popup.fxml")); ImageView imageView = (ImageView) parent.lookup("#imgMessage"); imageView.setImage(new Image(getClass().getResource("images/dialog-info.png").toString())); imageView.setOnMouseClicked(event->pu.hide()); Label lblMessage = (Label)parent.lookup("#lblMessage"); lblMessage.setText("메시지가 왔습니다."); pu.getContent().add(parent); pu.setAutoHide(true);//다른 윈도우로 포커스를 이동하면 popup자동 닫힘. pu.show(primaryStage); }
* Popup도 다이얼로그이다. => 소유자 윈도우가 필요하다. => show() 메서드를 호출할 때 매개값으로
소유자 윈도우인 Stage가 필요하다.
커스텀 다이얼로그
Stage를 직접 생성하면 다양한 내용의 다이얼로그를 만들 수 있다.
Stage dialog = new Stage(StageStyle.UTILITY);
dialog.initModality(Modality.WINDOW)MODAL);
dialog.initOnwer(primaryStage);
Stage 생성자 매개값에는 윈도우의 스타일을 결정짓는 StageStyle 열거 상수가 옴.
StageStyle 열거상수 설명
DECORATED 일반적 윈도우 스타일, 흰 배경, 제목줄에 장식(아이콘, 타이틀, 축소, 복원, 닫기 버튼 장식)이 있다.
UNDECORATED 흰 배경, 제목줄 X
TRANSPARENT 투명 배경, 제목줄 X
UNIFIED DECORATED와 같지만, 내용물의 경계선 X
UTILITY 흰 배경, 제목줄에 타이틀, 종료버튼만 있다.
매개값이 없는 기본 생성자로 Stage 생성 시 => DECORATED 원도우 생성.
initModality(Modality.WINDOW)MODAL) => 모달 다이얼로그로 설정.
미설정 시 모달리스 다이얼로그가 됨.
initOnwer(primaryStage) = > 소유자 원도우 설정.
ex) 확인 다이얼로그 내용 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <AnchorPane prefHeight="150.0" prefWidth="400.0" xmlns:fx="http://javafx.com/fxml"> <children> <ImageView fitHeight="50" fitWidth="50" layoutX="15" layoutY="15" preserveRatio="true"> <image><Image url="@images/dialog-info.png" /></image> </ImageView> <Button id="btnOk" layoutX="336.0" layoutY="104.0" text="확인" /> <Label id="txtTitle" layoutX="87.0" layoutY="33.0" prefHeight="15.0" prefWidth="290.0" /> </children> </AnchorPane> 확인 다이얼로그 실행. Stage dialog = new Stage(StageStyle.UTILITY); dialog.initModality(Modality.WINDOW_MODAL); dialog.initOwner(primaryStage); dialog.setTitle("확인 다이얼로그"); Parent parent = FXMLLoader.load(getClass().getResource("custom_dialog.fxml")); Label txtTitle = (Label) parent.lookup("#txtTitle"); txtTitle.setText("확인하시겠습니까?"); Button btnOk = (Button) parent.lookup("#btnOk"); btnOk.setOnAction(event->dialog.close()); Scene scene = new Scene(parent); dialog.setScene(scene); dialog.setResizable(false); dialog.show();
컨트롤러에서 primaryStage 사용
컨트롤러에서 다이얼로그를 실행할 때 -> 소유자 윈도우가 될 primaryStage 필요
컨트롤러에서 primaryStage를 얻는 방법 1. 메인 클래스에서 전달. primaryStage는 메인 클래스의 start() 매개값으로 전달된다 -> start() 메서드에서 컨트롤러로 primaryStage를 전달하면 됨. FXML 루트태그 fx:controller 속성에 지정된 컨트롤러 클래스는 FXMLLoader가 FXML을 로딩할 때 객체로 생성됨. FXMLLoader는 생성된 컨트롤러를 리턴하는 getController() 메서드 제공. * getController() 는 인스턴스 메서드이다 => FXMLLoader 객체가 필요. -> FXMLLoader의 정적 메서드인 load()의 호출 코드는 인스턴스 메서드 load()호출 코드로 바뀌어야 함. FXMLLoader loader = new FXMLLoader(getClass().getResource("root.fxml")); Parent root = loader.load(); RootController controller = loader.getController(); controller.setPrimaryStage(primaryStage); 컨트롤러의 setPrimaryStage() 메서드를 호출하면서 primaryStage를 매개값으로 전달함. * => 컨트롤러 클래스는 필드와 setter 메서드를 추가해 두어야 함. public class RootController implements Initializable { private Stage primaryStage; public void setPrimaryStage(Stage primaryStage) { this.primaryStage = primaryStage; } ..... }
2. 컨터이너 or 컨트롤러로부터 얻음.
컨테이너나 컨트롤의 getScene() 는 자신이 포함된 Scene 객체 리턴.
Scene의 getWindow() 는 자신이 보여주는 Stage 객체 리턴.
컨트롤러에서 primaryStage 객체를 얻는 코드
=>
Stage primaryStage = (Stage) 컨트롤.getScene().getWindow();
* initialize() 안에서는 사용 불가.
=> 아직 primaryStage가 생성되지 않아서.
메인 클래스의 start() 메서드에서 Scene 객체를 생성하고 primaryStage에 Scene을 설정해야 위 코드가 정상 동작 때문
에 이벤트 처리 메서드 내에서 위 코드를 사용해야 함.
JavaFX 다이얼로그 전체 예제) root.fxml <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <?import javafx.scene.control.*?> <?import javafx.geometry.*?> <HBox xmlns:fx="http://javafx.com/fxml" fx:controller="thisisjava.RootController" alignment="TOP_LEFT" spacing="10.0" > <children> <Button text="Open FileChooser" onAction="#handleOpenFileChooser"/> <Button text="Save FileChooser" onAction="#handleSaveFileChooser"/> <Button text="DirectoryChooser" onAction="#handleDirectoryChooser"/> <Button text="Popup" onAction="#handlePopup"/> <Button text="Custom Dialog" onAction="#handleCustom"/> </children> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </padding> </HBox> popup.fxml <?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.*?> <?import java.lang.*?> <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <?import javafx.scene.layout.*?> <HBox xmlns:fx="http://javafx.com/fxml" alignment="CENTER_LEFT" style="-fx-background-color: black; -fx-background-radius: 20;" > <children> <ImageView id="imgMessage" fitHeight="30" fitWidth="30" preserveRatio="true"/> <Label id="lblMessage" style="-fx-text-fill: white;"> <HBox.margin> <Insets left="5.0" right="5.0" /> </HBox.margin> </Label> </children> </HBox> costom_dialog.fxml <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <AnchorPane prefHeight="150.0" prefWidth="400.0" xmlns:fx="http://javafx.com/fxml"> <children> <ImageView fitHeight="50" fitWidth="50" layoutX="15" layoutY="15" preserveRatio="true"> <image><Image url="@images/dialog-info.png" /></image> </ImageView> <Button id="btnOk" layoutX="336.0" layoutY="104.0" text="확인" /> <Label id="txtTitle" layoutX="87.0" layoutY="33.0" prefHeight="15.0" prefWidth="290.0" /> </children> </AnchorPane> 자바1) package thisisjava; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class AppMain extends Application { @Override public void start(Stage primaryStage) throws Exception { FXMLLoader loader = new FXMLLoader(getClass().getResource("root.fxml")); Parent root = loader.load(); RootController controller = loader.getController(); controller.setPrimaryStage(primaryStage); Scene scene = new Scene(root); primaryStage.setTitle("JavaFX 다이얼로그"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 자바2) package thisisjava; import java.io.File; import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Modality; import javafx.stage.Popup; import javafx.stage.Stage; import javafx.stage.StageStyle; public class RootController implements Initializable { @Override public void initialize(URL location, ResourceBundle resources) { } private Stage primaryStage; public void setPrimaryStage(Stage primaryStage) { this.primaryStage = primaryStage; } public void handleOpenFileChooser(ActionEvent e) { FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().addAll( new ExtensionFilter("Text Files", "*.txt"), new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif"), new ExtensionFilter("Audio Files", "*.wav", "*.mp3", "*.aac"), new ExtensionFilter("All Files", "*.*")); File selectedFile = fileChooser.showOpenDialog(primaryStage); if (selectedFile != null) { System.out.println(selectedFile.getPath()); } } public void handleSaveFileChooser(ActionEvent e) { FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*.*")); File selectedFile = fileChooser.showSaveDialog(primaryStage); if (selectedFile != null) { System.out.println(selectedFile.getPath()); } } public void handleDirectoryChooser(ActionEvent e) { DirectoryChooser directoryChooser = new DirectoryChooser(); File selectedDir = directoryChooser.showDialog(primaryStage); if (selectedDir != null) { System.out.println(selectedDir.getPath()); } } public void handlePopup(ActionEvent e) throws Exception { Popup popup = new Popup(); Parent parent = FXMLLoader.load(getClass().getResource("popup.fxml")); ImageView imageView = (ImageView) parent.lookup("#imgMessage"); imageView.setImage(new Image(getClass().getResource("images/dialog-info.png").toString())); imageView.setOnMouseClicked(event->popup.hide()); Label lblMessage = (Label)parent.lookup("#lblMessage"); lblMessage.setText("메시지가 왔습니다."); popup.getContent().add(parent); popup.setAutoHide(true); popup.show(primaryStage); } public void handleCustom(ActionEvent e) throws Exception { Stage dialog = new Stage(StageStyle.UTILITY); dialog.initModality(Modality.WINDOW_MODAL); dialog.initOwner(primaryStage); dialog.setTitle("확인 다이얼로그"); Parent parent = FXMLLoader.load(getClass().getResource("custom_dialog.fxml")); Label txtTitle = (Label) parent.lookup("#txtTitle"); txtTitle.setText("확인하시겠습니까?"); Button btnOk = (Button) parent.lookup("#btnOk"); btnOk.setOnAction(event->dialog.close()); Scene scene = new Scene(parent); dialog.setScene(scene); dialog.setResizable(false); dialog.show(); } }