JavaFX : 초기화 중에 컨트롤러에서 스테이지를 가져 오는 방법은 무엇입니까?
컨트롤러 클래스에서 스테이지 이벤트 (즉, 숨기기)를 처리하고 싶습니다. 그래서 제가해야 할 일은 리스너를 추가하는 것입니다.
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
하지만 문제는 초기화가
Parent root = FXMLLoader.load(getClass().getResource("MyGui.fxml"));
그리고 전에
Scene scene = new Scene(root);
stage.setScene(scene);
따라서 .getScene ()은 null을 반환합니다.
내가 찾은 유일한 해결 방법은 myPane.sceneProperty ()에 리스너를 추가하는 것입니다. 그리고 그것이 null이 아닐 때 씬이 생기면 .windowProperty () my! goddamn! 마침내 단계를 검색하는 리스너 처리. 그리고 그것은 모두 이벤트를 준비하기 위해 원하는 리스너를 설정하는 것으로 끝납니다. 듣는 사람이 너무 많다고 생각합니다. 내 문제를 해결하는 유일한 방법입니까?
FXMLLoader
를 통해 초기화 후 컨트롤러의 인스턴스를 가져올 수 getController()
있지만 FXMLLoader
정적 메서드를 사용 하는 대신 인스턴스를 생성해야합니다 .
load()
나중에 컨트롤러에 직접 호출 한 후 스테이지를 전달합니다 .
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyGui.fxml"));
Parent root = (Parent)loader.load();
MyController controller = (MyController)loader.getController();
controller.setStageAndSetupListeners(stage); // or what you want to do
필요한 것은 AnchorPane
ID 를 제공하는 것뿐입니다. 그러면 ID를 얻을 수 있습니다 Stage
.
@FXML private AnchorPane ap;
Stage stage = (Stage) ap.getScene().getWindow();
여기에서 Listener
필요한 것을 추가 할 수 있습니다 .
편집 : 아래 EarthMind에서 언급했듯이 AnchorPane
요소 일 필요는 없습니다 . 정의한 모든 요소가 될 수 있습니다.
나는 그것이 당신이 원하는 대답이 아니라는 것을 알고 있지만, IMO에서 제안 된 해결책은 좋지 않습니다. 왜? 응용 프로그램 상태에 따라 달라지기 때문입니다. JavaFX에서 컨트롤, 장면 및 무대는 서로 의존하지 않습니다. 즉, 컨트롤은 장면에 추가하지 않고도 살 수 있고 장면은 무대에 연결하지 않고도 존재할 수 있습니다. 그런 다음 순간 t1에서 제어가 장면에 연결될 수 있고 순간 t2에서 해당 장면이 무대에 추가 될 수 있습니다 (그리고 서로의 특성을 관찰 할 수있는 이유를 설명합니다).
따라서 컨트롤러 참조를 가져오고 메서드를 호출하고 스테이지를 전달하여 애플리케이션에 상태를 추가하는 방법을 제안합니다. 즉, 스테이지가 생성 된 직후 적절한 순간에 해당 메서드를 호출해야합니다. 즉, 지금 주문을 따라야합니다. 1- 단계 생성 2- 생성 된이 단계를 메소드를 통해 컨트롤러에 전달합니다.
이 접근 방식에서는이 순서를 변경할 수 없거나 변경해서는 안됩니다. 그래서 무국적 상태를 잃었습니다. 그리고 소프트웨어에서 일반적으로 상태는 악합니다. 이상적으로 메서드는 호출 순서를 요구하지 않아야합니다.
그렇다면 올바른 솔루션은 무엇입니까? 두 가지 대안이 있습니다.
1- 당신의 접근 방식, 컨트롤러 청취 속성에서 무대를 얻습니다. 이것이 올바른 접근 방식이라고 생각합니다. 이렇게 :
pane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
if (oldScene == null && newScene != null) {
// scene is set for the first time. Now its the time to listen stage changes.
newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
if (oldWindow == null && newWindow != null) {
// stage is set. now is the right time to do whatever we need to the stage in the controller.
((Stage) newWindow).maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
}
});
}
});
2- 당신은 당신이 만드는 곳에서 당신이해야 할 일을합니다 Stage
(그리고 그것은 당신이 원하는 것이 아닙니다).
Stage stage = new Stage();
stage.maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
stage.setScene(someScene);
...
The simplest way to get stage object in controller is:
Add an extra method in own created controller class like (it will be a setter method to set the stage in controller class),
private Stage myStage; public void setStage(Stage stage) { myStage = stage; }
Get controller in start method and set stage
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage);
Now you can access the stage in controller
Assign fx:id or declare variable to/of any node: anchorpane, button, etc. Then add event handler to it and within that event handler insert the given code below:
Stage stage = (Stage)((Node)((EventObject) eventVariable).getSource()).getScene().getWindow();
Hope, this works for you!!
You can get with node.getScene
, if you don't call from Platform.runLater
, the result is a null value.
example null value:
node.getScene();
example no null value:
Platform.runLater(() -> {
node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
//your event
});
});
'developer tip' 카테고리의 다른 글
Karma-Jasmine 단위 테스트 사례를 작성하는 동안 "오류 : 라우터에 대한 공급자 없음" (0) | 2020.09.24 |
---|---|
내 애플리케이션의 설정 번들에 애플리케이션 버전 개정을 표시하려면 어떻게해야합니까? (0) | 2020.09.23 |
“? android : attr / activatedBackgroundIndicator”는 어떻게 작동합니까? (0) | 2020.09.23 |
PHP는 datetime을 UTC로 변환 (0) | 2020.09.23 |
Google지도의 위성보기를 비활성화하는 방법은 무엇입니까? (0) | 2020.09.23 |