JavaFx 다이얼로그

주 윈도우에서 알림 또는 사용자의 입력을 위해서 실행되는 서브 윈도우

자체적으로 실행될 수 없고, 주 윈도우(소유자 윈도우)에 의해서 실행

 

- 모달 다이얼로그

: 다이얼로그를 닫기 전 까지 소유자 윈도우를 사용할 수 없음

- 모달리스 다이얼로그

: 다이얼로그를 닫아도 소유자 윈도우 계속 사용 가능

 

1. FileChooser, DIrectoryChooser

- FileChooser

: 로컬 PC의 파일을 선택할 수 있는 다이얼로그 - 컨트롤이 아니기 때문에 FXML에서 선언할 수 없음

: showOpenDialog() 또는 showSaveDialog()를 호출해야 함

: 모달 다이얼로그 이므로 [열기] 또는 [저장] 버튼을 클릭하거나, [취소] 버튼을 클릭하기 전까지는 소유자 윈도우를 사용할 수 없음

- DirectoryChooser

: 파일이 아닌 디렉토리(폴더)를 선택하고 싶을 때 사용

 

2. Popup

투명한 컨테이너를 제공하는 모달리스 다이얼로그

: 윈도우의 기본 장식(아이콘, 제목, 최소화 및 복원 버튼, 닫기 버튼) 없음

: 자바 코드로 작성하거나, FXML 파일로 작성

: 다른 윈도우보다 최상위 위치에 놓임

: 모달리스 다이얼로그 - Popup을 닫기 위해서는 주 윈도우(소유자 윈도우)를 닫거나, Popup 안에 추가된 컨트롤의 이벤트를 처리해서 hide() 메소드를 호출해야 함

: setAutoHide(true)로 설정 시 다른 윈도우로 포커스를 이동하면 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;" >
   <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>

 

3. 커스텀 다이얼로그

다양한 내용의 다이얼로그를 만들고 싶다면 Stage로 직접 생성

StageStyle 열거 상수와 윈도우 스타일

 

확인 다이얼로그 내용을 정의

<?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>

 

4. 컨트롤러에서 primaryStage 사용

: 컨트롤러에서 다이얼로그를 실행할 때, 소유자 윈도우가 될 primaryStage가 필요

 

- 메인 클래스에서 전달하는 방법

: 메인 클래스의 start() 매개값으로 전달

- 컨테이너 또는 컨트롤러로부터 얻는 방법

: initialize() 메소드 안에서는 사용 불가

 

실행 클래스

package sec09.exam01_dialog;

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("AppMain");
		primaryStage.setScene(scene);
		primaryStage.show();
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

 

선언적 레이아웃

<?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="sec09.exam01_dialog.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" onAction="#handleCustom"/>
   </children>
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
</HBox>

 

컨트롤러

package sec09.exam01_dialog;

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();
	}
}

+ Recent posts