Как передать объект, созданный в FXML Controller1, в Controller2 внутреннего элемента управления FXML
У меня есть приложение 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 ответа
В 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 />
Я использую 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" . может быть, это вызов контроллера автоматически.