Как передать объект, созданный в FXML Controller1, в Controller2 внутреннего элемента управления FXML - PullRequest
14 голосов
/ 15 марта 2012

У меня есть приложение JavaFX 2.0, которое состоит из двух файлов FXML и двух контроллеров для них + один «основной» файл .java.

В момент запуска FXML1 инициализируется, как показано ниже:

public void start(Stage stage) throws Exception {
    stage.setTitle("Demo Jabber JavaFX Chat");

    Parent root = FXMLLoader.load(getClass().getResource("fxml_example.fxml"),
        ResourceBundle.getBundle("fxmlexample.fxml_example"));        
    Scene scene = new Scene(root, 226, 264);
    stage.setScene(scene);
    scene.getStylesheets().add("fxmlexample/fxmlstylesheet.css");
    stage.show();
}

Затем, когда нажимается кнопка из scene1, в ее обработчике событий в классе Controller1 я меняю корень scene1, чтобы показать новый графический вид для пользователя.И в этом контроллере я инициализирую некоторый объект.Например, вот так:

public class FXMLExampleController {
   //some fields...
   private MySuperObject c;
   @FXML protected void handleSubmitButtonAction(ActionEvent event) {
    //some fields...
    c = new MySuperObject(); //here i initialize my object, i'm interested in
    try {
        c.login(username, password); // some actions with this object, which i need to make.
        Scene cc = buttonStatusText.getScene();
        Parent root = null;
        try {
            //changing a scene content...
            root = FXMLLoader.load(getClass().getResource("fxml_example2.fxml"),
            ResourceBundle.getBundle("fxmlexample.fxml_example"));
        } catch (IOException ex) {
            Logger.getLogger(FXMLExampleController.class.getName()).log(Level.SEVERE, null, ex);
        }
        cc.setRoot(root);
      }

И после этого мне нужно поработать с этим объектом на следующей сцене, и это должен быть НЕ новый экземпляр того же класса, но объект,Я инициализировал первую сцену.

Я понимаю, как сделать все это, используя "стандартную Java", но я немного запутался в этой задаче, используя JavaFX + FXML.

Ответы [ 2 ]

25 голосов
/ 23 мая 2012

В FX 2.2 был представлен новый API для контроллера-узла:

// create class which is both controller and node
public class InnerFxmlControl extends HBox implements Initializable {
  @FXML public ComboBox cb;

  public InnerFxmlControl () {
     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml_example2.fxml"));
     fxmlLoader.setRoot(this);
     fxmlLoader.setController(this);
     try {
         fxmlLoader.load();            
     } catch (IOException exception) {
         throw new RuntimeException(exception);
     }
  }

со следующим fxml (тег заметки fx:root):

<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml">
  <children>
    <ComboBox fx:id="cb" />
  </children>
</fx:root>

Таким образом, вы создали новый элемент управления, который вы можете использовать как обычные элементы управления JavaFX. Например. в вашем случае:

@FXML protected void handleSubmitButtonAction(ActionEvent event) {
    // you just create new control, all fxml tricks are encapsulated
    InnerFxmlControl root = new InnerFxmlControl();
    // and you can access all its' methods and fields including matched by @FXML tag:
    root.cb.getItems().add("new item");

    Scene cc = buttonStatusText.getScene();
    cc.setRoot(root);
  }

и в формате fxml:

<InnerFxmlControl />
3 голосов
/ 16 июня 2013

Я использую 1.7.0_21, теперь он может кодироваться следующим образом: в файле fxml основного приложения

<VBox ...>
      <fx:include fx:id="tom" source="Tom.fxml" />
</VBox>

и включенный файл fxml могут определять свой собственный файл fxml, например:

<AnchorPane id="AnchorPane" fx:id="tomPan" ... xmlns:fx="http://javafx.com/fxml" fx:controller="**com.tom.fx.TomController**">

и затем в главном контроллере приложения требуется контроллер "Tom.fxml", подобный следующему:

 @FXML private TomController tomController;

обратите внимание на "@FXML".может быть, он вызывает контроллер автоматически.

...