컨트롤러 클래스에서 스테이지 이벤트 (즉, 숨기기)를 처리하고 싶습니다. 그래서 제가해야 할 일은 리스너를 추가하는 것입니다.
((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);
...
답변
컨트롤러에서 스테이지 객체를 얻는 가장 간단한 방법은 다음과 같습니다.
-
(컨트롤러 클래스에서 스테이지를 설정하는 setter 메소드가 될 것입니다)와 같이 자체 생성 된 컨트롤러 클래스에 추가 메소드를 추가합니다.
private Stage myStage; public void setStage(Stage stage) { myStage = stage; }
-
시작 방법에서 컨트롤러 가져 오기 및 단계 설정
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage);
-
이제 컨트롤러에서 스테이지에 액세스 할 수 있습니다.
답변
fx : id를 할당 하거나 모든 노드 (anchorpane, button 등)에 변수를 선언합니다. 그런 다음 여기에 이벤트 핸들러를 추가하고 해당 이벤트 핸들러 내에 아래에 주어진 코드를 삽입합니다.
Stage stage = (Stage)((Node)((EventObject) eventVariable).getSource()).getScene().getWindow();
희망, 이것은 당신을 위해 작동합니다 !!
답변
Platform.runLater는 초기화가 완료 될 때까지 실행을 방지합니다. 이 경우 창 너비를 조정할 때마다 목록보기를 새로 고치고 싶습니다.
Platform.runLater(() -> {
((Stage) listView.getScene().getWindow()).widthProperty().addListener((obs, oldVal, newVal) -> {
listView.refresh();
});
});
당신의 경우
Platform.runLater(()->{
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
});
답변
당신과 함께 얻을 수 있습니다 node.getScene
당신은에서 호출하지 않는 경우, Platform.runLater
결과는 널 값입니다.
null 값의 예 :
node.getScene();
null 값이없는 예 :
Platform.runLater(() -> {
node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
//your event
});
});