我有一个包含 hbox(root)和2个vbox 的场景,每个vbox包含单独的fxml文件和控制器。第一个vbox包含一个按钮和textfield,第二个包含一个listview,所以我需要的是当我单击textfield上的按钮值时应该传递给listview并更新而不加载一个全新的阶段。
注意:我使用
fx:include id="v1"
作为vbox儿童
在fxml中并初始化主控制器中的控制器,但遗憾的是,如果我想要替换vbox子进程 新的fxml意味着,我该怎么办?那么任何简单的工作解决方案呢?
这是我的maincontroller.java
public class MainController implements Initializable{
@FXML
private VBox v1;
@FXML
private VBox v2;
@Override
public void initialize(URL url, ResourceBundle rb) {
try {
v1.getChildren().add(FXMLLoader.load(getClass().getResource("voneFX.fxml")));
v2.getChildren().add(FXMLLoader.load(getClass().getResource("vtwoFX.fxml")));
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
voneController.java
public class voneController {
@FXML private TextField txt1;
@FXML private Button btn1Send;
@FXML private void btn1SendClicked(ActionEvent event){
//Here i would like to call updateListView method
}
}
votwoController.java
public class vtwoController{
@FXML
private ListView<ListModel> sampleListview;
ObservableList<ListModel> items = FXCollections.observableArrayList ();
public void updateListView() {
//This is the method which is called when user hit the button.
}
}
答案 0 :(得分:0)
要制作您想要的东西,您需要访问控制器(控制器本身必须能够相互通信)。 FXMLLoader
提供了几种访问控制器的选项。第一个选项是自动将f include
中包含的fxml组件注入fxml文件中。
<fx:include fx:id="childView" source="child.fxml"/>
为了注入控制器,必须使用后缀Controller在child.fxml
中指定的名称声明fx:id
中指定的控制器类型的字段。当然,使用@FXML
进行注释。
public class MainController {
@FXML
private ChildController childViewController;
...
}
如果您要使用动态变化的上下文,您可以手动创建控制器并将其传递给FXMLLoader
,这将通过注入相应的字段或只是选择初始化的实例来初始化它。
此处,首先致电FXMLLoader#load()
,然后FXMLLoader#getController()
,这一点非常重要。
FXMLLoader loader = new FXMLLoader(getClass().getResource("/resource/layout/child.fxml"));
Parent parent = loader.load();
ChildController controller = loader.getController();
手动创建控制器时,您必须先调用FXMLLoader#setController()
然后再调用FXMLLoader#load()
。
ChildController controller = new ChildController();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/resource/layout/child.fxml"));
loader.setController(controller);
Parent parent = loader.load();
因此,控制器之间的通信是微不足道的,我认为没有必要解释。
<强>更新强>
如何在对象之间进行通信的示例。 这些是使用该应用程序的两个视图:
child.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<HBox alignment="CENTER_LEFT" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ChildController">
<children>
<Label text="Child View" />
<TextField fx:id="textField" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" text="Send to parent" onAction="#handleSendButton"/>
</children>
</HBox>
sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController">
<children>
<HBox spacing="5.0">
<children>
<TextField fx:id="textField" editable="false" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" text="Refresh" onAction="#handleRefreshButton"/>
</children>
</HBox>
<HBox fx:id="childContainer">
<fx:include fx:id="childView" source="child.fxml" />
</HBox>
</children>
</VBox>
分别是两个控制器。
public class ChildController {
@FXML
private TextField textField;
private Consumer<String> consumer;
public void addConsumer(Consumer<String> consumer) {
this.consumer = consumer;
}
@FXML
private void handleSendButton(ActionEvent event) {
if(consumer == null) {
return;
}
consumer.accept(textField.getText());
}
}
在此处,按“刷新”按钮会重新加载插入的视图。
public class MainController {
@FXML
private TextField textField;
@FXML
private HBox childContainer;
@FXML
private ChildController childViewController;
@FXML
private void initialize() {
childViewController.addConsumer(textField::setText);
}
@FXML
private void handleRefreshButton(ActionEvent event) {
try {
textField.setText("");
FXMLLoader loader = new FXMLLoader(getClass().getResource("child.fxml"));
Parent parent = loader.load();
childViewController = loader.getController();
childViewController.addConsumer(textField::setText);
childContainer.getChildren().setAll(parent);
}
catch (IOException e) {
e.printStackTrace();
}
}
}