2012-01-20 3 views
7

Кажется, что WindowEvent.WINDOW_SHOWN никогда не отправляется ни на один из узлов в графе сцены, ни в любом случае (я не мог найти) знать, когда узел виден/отображен/показан. Например:Как прослушивать WindowEvent.WINDOW_SHOWN в узлах графа сцены?

TestLauncher.java

package com.example.javafx.event; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class TestLauncher extends Application 
{ 
    public static void main(String[] args) 
    { 
     Application.launch(TestLauncher.class, args); 
    } 

    @Override 
    public void start(Stage stage) throws Exception 
    { 
     Parent root = FXMLLoader.load(TestController.class.getResource("TestView.fxml")); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 
     stage.show(); 
    } 
} 

TestController.java

package com.example.javafx.event; 

import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.event.EventHandler; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.Parent; 
import javafx.scene.control.TextField; 
import javafx.stage.WindowEvent; 

public class TestController implements Initializable 
{ 
    @FXML private Parent root; 
    @FXML private TextField serverAddressInput; 
    @FXML private TextField usernameInput; 

    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     serverAddressInput.setText("127.0.0.1"); 

     //won't work because stage isn't visible yet 
     trySetFocusOnUsernameInput1(); 

     //apparently Stage never passes on any WindowEvents to the children... 
     trySetFocusOnUsernameInput2(); 
    } 

    private void trySetFocusOnUsernameInput1() 
    { 
     usernameInput.requestFocus(); 
    } 

    private void trySetFocusOnUsernameInput2() 
    { 
     root.addEventFilter(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>() 
     { 
      @Override 
      public void handle(WindowEvent window) 
      { 
       usernameInput.requestFocus(); 
      } 
     }); 

     root.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>() 
     { 
      @Override 
      public void handle(WindowEvent window) 
      { 
       usernameInput.requestFocus(); 
      } 
     }); 
    } 

    public void handleWindowShownEvent() 
    { 
     usernameInput.requestFocus(); 
    } 
} 

TestView.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<VBox 
    xmlns:fx="http://javafx.com/fxml" 

    fx:id="root" 
    fx:controller="com.example.javafx.event.TestController" 

    prefHeight="150" 
    prefWidth="200" 
> 
    <children> 
     <TextField fx:id="serverAddressInput" /> 
     <TextField fx:id="usernameInput" /> 
    </children> 
</VBox> 

Итак, на самом деле, как еще узел может осознать тот факт, что он отображается/отображается/отображается?

ответ

4

Я предполагаю, одно из возможных решений состоит в добавлении следующего метода TestController.java

public void handleWindowShownEvent() 
    { 
     usernameInput.requestFocus(); 
    } 

, а затем изменить метод start в TestLauncher к следующему:

@Override 
    public void start(Stage stage) throws Exception 
    { 
     FXMLLoader loader = new FXMLLoader(); 
     Parent root = (Parent)loader.load(TestController.class.getResourceAsStream("TestView.fxml")); 
     final TestController controller = (TestController)loader.getController(); 
     stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>() 
     { 
      @Override 
      public void handle(WindowEvent window) 
      { 
       controller.handleWindowShownEvent(); 
      } 
     }); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 
     stage.show(); 
    } 

Я бы очень приветствовал другие решения, поскольку этот кажется слишком неуклюжим ...

+0

Уважаемый Андрей. Мое приложение имеет количество контроллеров, и мне нужно сделать это в середине некоторого потока пользовательского интерфейса. Когда я добавлю обработчик событий WindowEvent.WINDOW_SHOWN, как вы упомянули, он попытается выполнить это место обработчика событий, которое я объявил, что означает выполнение запуска приложения (метод Stage), после чего я получил некоторые исключения Null Pointer. Не могли бы вы рассказать мне, как я могу решить эту проблему. Благодарю. – Channa

+0

Если вас все еще интересует решение анотера (4y later ..), взгляните на мой ответ –

3

Другого решения, по общему признанию, не очень сексуально, но разъединяет узел из приложения:

root.sceneProperty().addListener(new ChangeListener<Scene>() { 
    @Override 
    public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) { 
    newValue.windowProperty().addListener(new ChangeListener<Window>() { 
     @Override 
     public void changed(ObservableValue<? extends Window> observable, Window oldValue, Window newValue) { 
     newValue.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<WindowEvent>() { 
      @Override 
      public void handle(WindowEvent event) { 
      usernameInput.requestFocus(); 
      } 
     }); 
     } 
    }); 
    } 
}); 

больше смысла в моем случае.

+2

Я думаю, что это лучшее решение из-за развязки – DevWurm

 Смежные вопросы

  • Нет связанных вопросов^_^