JavaFX:绑定不适用于包含的 FXML



我希望我的包含/嵌入式基于 fxml 的控件通知其包含的对象(父视图(有关其状态/属性的更改。正如你在下面看到的,我写了一个Container.fxml,包括一个View.fxml和根据控制器类,名为"Container.java"和">View.java"。

ViewController.java的文本字段更改时,其 StringProperty 'textProperty_View' 将更新。这似乎工作正常,因为 OnAction 处理程序按预期调用。

但是父ContainerController.java 中的侦听器不会触发,尽管我将其 StringProperty 绑定到ViewController的 StringProperty.java并为此属性添加了 ChangeListener。

我做错了什么?

附言:

  • 我通过做同样的事情简化了示例,而无需fx:include查看绑定是否有效。它有效。但是当我像描述的问题一样嵌入视图时不会(请参阅下面的代码(
  • 我正在使用javafx-15-ea+3和java11

AppStarter.java


public class AppStarter extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Container.fxml"));
Scene scene = new Scene(root, 300, 275);
stage.setScene(scene);
stage.show();
}
}

ContainerController.fxml

<HBox xmlns="http://javafx.com/javafx/10.0.2-internal" 
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="gui.ContainerController">
<fx:include source="View.fxml" fx:id="view"/>
<!-- <TextField fx:id="textFieldMain" prefWidth="200" onAction="#onActionMain"/>  -->
</HBox>

容器控制器.java

public class ContainerController implements Initializable {
private final StringProperty textProperty_Main = new SimpleStringProperty();
@FXML
private ViewController viewController;
//    @FXML
//    void onActionMain(ActionEvent event) {
//        System.out.println("onActionMain " + viewController.getTextProperty_View());
//    }
@Override
public void initialize(URL location, ResourceBundle resources) {
textProperty_Main.bind(viewController.textProperty_ViewProperty());
textProperty_MainProperty().addListener((observable, oldValue, newValue) ->
System.out.println("textProperty of Container changed to: " + getTextProperty_Main())
);
}
public String getTextProperty_Main() {
return textProperty_Main.get();
}
public StringProperty textProperty_MainProperty() {
return textProperty_Main;
}
}

View.fxml

<HBox xmlns="http://javafx.com/javafx" 
xmlns:fx="http://javafx.com/fxml" 
fx:controller="gui.ViewController">
<TextField fx:id="textField" prefWidth="200" onAction="#onAction">Unset</TextField>
</HBox>

视图控制器.java

public class ViewController {
private final StringProperty textProperty_View = new SimpleStringProperty();
@FXML
private TextField textField;
@FXML
void onAction(ActionEvent event) {
textProperty_ViewProperty().setValue(textField.getText());
System.out.println("textProperty of View changed to: " + textProperty_ViewProperty().getValue());
}
public String getTextProperty_View() {
return textProperty_View.get();
}
public StringProperty textProperty_ViewProperty() {
return textProperty_View;
}
}

您看到的问题非常令人沮丧:JavaFX 绑定使用WeakListener来实现绑定。这意味着,如果绑定超出范围,侦听器有资格进行垃圾回收,因此可能会停止工作。(在我的设置中,您的代码实际上可以工作,但是如果我在某处调用System.gc(),它会立即停止工作。

我能找到的唯一解决方法是在应用程序类中显式保留对ContainerController的引用(因为ContainerController具有对ViewController的引用,并且ViewController具有对文本字段的引用,这通过文本字段上的侦听器创建了绑定侦听器的路径, 等(:

public class AppStarter extends Application {

private ContainerController controller ;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Container.fxml"));
Parent root = loader.load();
this.controller = loader.getController();
Scene scene = new Scene(root, 300, 275);
stage.setScene(scene);
stage.show();
}
}

最新更新