我有一个用NetBeans 8编写的JavaFX / Java 8应用程序(没有SceneBuilder
)。
我的应用程序有一个主窗口,它有自己的FXML文件(primary.fxml)和自己的控制器类(FXMLPrimaryController.java)。 FXML中的一个项目是TextArea
。 FXMLPrimaryController.java中的一些方法是附加到TextArea
。
这个应用程序现在生成第二个窗口(另一个" stage"),它有自己的FXML(second.fxml)和它自己的控制器类(FXMLsecondController.java)。
在第二个控制器类中,如何访问主要文件中的TextArea?
以下是相关代码的示例:
primary.fxml:
<Button text="press me!" onAction="#openSecondWindow" />
<TextArea fx:id="myArea" />
FXMLPrimaryController.java:
public class FXMLPrimaryController implements Initializable {
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML private TextArea myArea;
final public void writeToTextArea() {
myArea.appendText("hi!");
}
@FXML
private void openSecondWindow(ActionEvent event) throws Exception {
Group root = new Group();
Stage stage = new Stage();
AnchorPane frame = FXMLLoader.load(getClass().getResource("second.fxml"));
root.getChildren().add(frame);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
second.fxml没什么特别的。假设有一个onAction="#writeSomething"
的按钮。
在FXMLsecondController.java中,我想要一个引用上述TextArea
的函数。
答案 0 :(得分:10)
为辅助控制器加载FXML时,请执行以下操作:
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("second.fxml"));
AnchorPane frame = fxmlLoader.load();
FXMLSecondaryController c = (FXMLSecondaryController) fxmlLoader.getController();
然后您可以将引用传递给第二个控制器。这可能只是TextArea。
编辑:
替换了上面代码段中的load()
来电并添加了setLocation()
来电。旧行AnchorPane frame = fxmlLoader.load(getClass().getResource("second.fxml"));
错误,因为它调用了静态load
函数,这在此处没用。
编辑:
(更改了上面的代码段,以便更好地匹配您的变量名称。) 上面的代码片段替换了代码的这一部分:
AnchorPane frame = FXMLLoader.load(getClass().getResource("second.fxml"));
该行使用FXMLLoader加载视图,并创建控制器的实例 - 在本例中为FXMLSecondaryController
。但是,您不能使用静态FXMLLoader.load
方法,需要FXMLLoader
的实例。该实例在加载后保存对控制器的引用,您可以使用getController()
检索该引用。并且您需要将返回的值强制转换为控制器类(使用(FXMLSecondaryController)
)。
您的主控制器有一个字段:
@FXML private TextArea myArea;
它包含对TextArea
的引用,并由fxml加载器初始化。 (如果删除@FXML
注释,则加载程序将不会触及它。)
在辅助控制器中,添加以下字段:
public TextArea primaryTextArea;
请注意@FXML
已消失(fxml加载程序不会触及该字段)以及private
(您想设置字段,因此其他人必须看到它)。
现在,您可以在加载控制器后设置此字段。所以回到加载代码:
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("second.fxml"));
AnchorPane frame = fxmlLoader.load();
FXMLSecondaryController c = (FXMLSecondaryController) fxmlLoader.getController();
// Add this too:
c.primaryTextArea = myArea;
编辑:替换了上面代码段中的load()
来电并添加了setLocation()
来电。旧行AnchorPane frame = fxmlLoader.load(getClass().getResource("second.fxml"));
错误,因为它调用了静态load
函数,这在此处没用。
FXMLSecondaryController
现在引用了主控制器的TextArea
。在其中一种方法中,您应该能够访问其内容:
public class FXMLSecondaryController implements Initializable {
// ...
public TextArea primaryTextArea;
// ...
@FXML
private void doSomething(ActionEvent event) throws Exception {
primaryTextArea.appendText("Hi ho!");
}
}
请注意,此解决方案不是最佳方法,但它很简单,可以作为一个开始。当然建议使用绑定。我会尝试创建一个包含数据的类,其他控制器绑定在该类上。但如果你现在采取简单的方法,那就足够了。
答案 1 :(得分:3)
我希望你能从FXMLPrimaryController公开TextField,并在FXMLsecondController中有一个TextField属性;然后在将各个部分组合在一起时设置该属性。但这不是一个好的设计,因为你将通过控制器公开视图的细节。
我确信你不想要TextArea而是second.fxml
中TextArea的数据。所以我建议在每个控制器中公开一个String属性并将它们绑定在一起。
public class FXMLPrimaryController {
private ReadOnlyStringWrapper text ;
@FXML
private TextArea myArea;
public void initialize() {
text= new ReadOnlyStringWrapper(this, "text");
text.bind(myArea.textProperty());
}
public ReadOnlyStringProperty textProperty() {
return text.getReadOnlyProperty();
}
public String getText() {
return text.get();
}
@FXML
private void openSecondWindow(ActionEvent event) throws Exception {
Group root = new Group();
Stage stage = new Stage();
AnchorPane frame = FXMLLoader.load(getClass().getResource("second.fxml"));
root.getChildren().add(frame);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
然后在你的FXMLsecondController中,你可以拥有
public class FXMLsecondController {
private StringProperty text ;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println(text.getValue());
}
public void initialize() {
text = new SimpleStringProperty(this, "text");
}
public StringProperty textProperty() {
return text ;
}
public String getText() {
return text.get();
}
}
然后你可以使用类似的东西绑定这两个
FXMLLoader primaryLoader = new FXMLLoader(getClass().getResource("primary.fxml"));
Parent textAreaHolder = (Parent) primaryLoader.load();
FXMLLoader secondaryLoader = new FXMLLoader(getClass().getResource("second.fxml"));
Parent textAreaUser = (Parent) secondaryLoader.load();
FXMLPrimaryController primaryController = (FXMLPrimaryController) textAreaHolder.getController();
FXMLsecondController secondController = (FXMLsecondController) textAreaUser.getController();
secondController.textProperty().bind(primaryController.textProperty());
现在绑定两个控制器的变量text
,您可以轻松使用在辅助控制器中主控制器的textarea中输入的值!