AlertBox 는 보통 새로운 윈도우를 하나 더 띄우는 것이다. 윈도우 GUI 프로그램을 사용하다 보면 기존의 윈도우에서 한 개의 윈도우를 더 오픈해야 하는 경우가 생긴다. 윈도우를 오래 사용하다보면 의식하지 않고 사용하는 것인데 윈도우 안에서 새로운 윈도우를 오픈하는 것이므로 두개의 창이 열린다.
Stage 구조를 두개 오픈하면 기존의 window 는 root 윈도우가 된다.
윈도우가 화면에 표시될 때 알 수 있지만 그러기 위해서는 윈도우를 열기 위한 작업을 반복하는 것이다.
이전 까지의 포스트를 통해서 javafx 는 다음의 구조라는 것을 알았다.
- Stage 클래스 : 처음 열리는 Stage 클래스가 root 윈도우다.
- Scene 클래스 : 하나의 Stage 클래스에 여러개의 Scene 들을 배치하여 이동할 수 있다.
- 레이아웃 매니저 : StackPane 이나 VBox, HBox 등이 있다.
- 컴포넌트들 (컨트롤, 컨테이너 등의 이름으로 불린다) 을 레이아웃 매니저에 추가한다.
Python 의 tkinter 같은 간단한 GUI 를 사용해봤다면 이 과정이 좀 복잡해 보일 지도 모른다. JavaFX 는 좀 더 번거롭기는 해도 기능이나 디자인 측면에서 tkinter 보다 우수하다.
하나의 창을 띄우기 위해서 이 모든 과정을 다 거쳐야 한다는 점에 주의한다.
* 새로운 창을 별도의 클래스에 정의한다. AlertBox라는 이름의 클래스를 정의한다.
이전까지 포스팅을 봤다면 충분히 이해할 내용이다.
package com;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class AlertBox {
public static void display(String title, String msg){
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(300);
Label label = new Label();
label.setText(msg);
Button closeButton = new Button("Close the window");
closeButton.setOnAction(e -> window.close());
VBox layout = new VBox(10);
layout.getChildren().addAll(label,closeButton);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout, 300, 500);
window.setScene(scene);
window.showAndWait();
}
}
여기서 modality 를 설정해주면 새로운 창을 닫기 전까지 원래 창(root)을 조작할 수 없다. 새로운 AlertBox 창이 닫혀야 된다. 아래의 코드로 설정한다.
window.initModality(Modality.APPLICATION_MODAL);
* 다음은 root 윈도우다. 이전 까지의 포스팅과 같은 코드이다.
다음의 코드는 위의 AlertBox의 메서드를 실행시킨다.
button.setOnAction(e -> AlertBox.display("Window", "alert box is awesome"));
package com;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
Stage window;
Scene scene;
Button button;
@Override
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
window.setTitle("Title Here");
button = new Button("CLICK");
button.setOnAction(e -> AlertBox.display("Window", "alert box is awesome"));
StackPane layout = new StackPane();
layout.getChildren().add(button);
scene = new Scene(layout, 500, 300);
window.setScene(scene);
window.show();
}
public static void main(String[] args) {
launch(args);
}
}
1. 실행하면 root 윈도우를 표시한다
2. 버튼을 클릭하면 서브 윈도우가 나타난다.
3. 서브윈도우가 닫히기 전까지는 root 윈도우의 조작이 되지 않는다. modality 설정
4. sub 윈도우 종료 root 윈도우 순서로 종료한다.
* Stage 클래스를 두개 사용하여 sub 윈도우와 root 윈도우를 동시에 열어봤다.
내가 사용하려는 윈도우의 숫자만큼 Stage 클래스가 필요하다는 점을 알 수 있다.
이번의 예제는 윈도우 간의 통신을 한다. 우선 AlertBox 와 비슷한 ConfirmBox 를 만든다. 흔히 우리가 yes or no 를 묻는 윈도우 창이다. Confirmation Window 라고 부른다. Yes 입력시에 true 를 No 에 false 를 리턴한다. 아까 AlertBox 와는 다르게 리턴형을 불린으로 정했다. 코드는 변수와 메서드를 따라가며 읽는다. 변수의 이름을 읽으면 자기 자신을 충분히 설명하도록 작성하는게 좋다.
많은 개발자들이 변수의 작성에 어려움을 겪고 있다. 좋은 변수의 작성은 곧 쉽게 읽혀지는 좋은 코드로 확장성이 좋아짐을 뜻한다.
package com;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class ConfirmBox {
static boolean answer;
public static boolean display(String title, String msg){
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(300);
Label label = new Label();
label.setText(msg);
// create 2 buttons
Button yesButton = new Button("Yes");
Button noButton = new Button("No");
yesButton.setOnAction(e -> {
answer = true;
window.close();
});
noButton.setOnAction(e -> {
answer = false;
window.close();
});
VBox layout = new VBox(10);
layout.getChildren().addAll(label, yesButton, noButton);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout, 300, 500);
window.setScene(scene);
window.showAndWait();
return answer;
}
}
이것을 받는 코드를 Main 클래스에 추가한다.
람다 식이 요긴하게 쓰인다. 람다식을 여러 줄에 입력하기 위해 e -> { } 대괄호의 사용법을 잘 봐둔다.
이렇게 하면 코드가 길어져도 인터페이스를 구현할 필요가 없기 때문에 유용하다.
어떤 버튼을 클릭했느냐에 따라서 콘솔창에 결과가 다르게 나타나는 것을 확인 할 수 있다. 콘솔창의 변화가 확인되면 흐름을 잡은 것이다. 이제 필요한 코드를 작성하여 변수에 연결시키면 프로그램의 기능을 구현할 수 있다.