0

我目前正在试验 JavaFX 的场景图。我遇到了一个我无法真正解释的奇怪问题。看看下面的代码:

        final BorderPane bp1 = new BorderPane();
    final Button button = new Button("CLICK ME");
    Scene sc1 = new Scene(bp1,100,100);     
    bp1.setCenter(button);
    stage1.setScene(sc1);
    stage1.show();

    Stage stage2 = new Stage();
    final BorderPane bp2 = new BorderPane();
    Scene sc2 = new Scene(bp2,100,100);
    stage2.setScene(sc2);
    stage2.setX(250);
    stage2.show();

    bp2.setCenter(button);
    bp1.setCenter(button);

我在这里要做的是将节点(按钮)添加到位于 stage1 场景中的 Borderpane。在代码的末尾,我尝试将节点添加到 stage2 上的不同场景(窗格)。这实际上有效。但最后一行没有。该按钮保留在 stage2 上。奇怪的是,如果我用网格窗格替换边框窗格,代码会按预期工作。为什么在这种情况下边框窗格的行为与网格窗格不同?

在这种情况下,我想到的另一个问题是:我假设每个场景(或舞台)恰好有 1 个场景图。那是对的吗?

4

1 回答 1

1

我猜你在 BorderPane 实现中发现了一个错误。BorderPane 管理其子项的方式有些特殊。您可以在此处找到 BorderPane 实现。我建议您在javafx jira提交错误报告

我的测试用例:

final BorderPane bp1 = new BorderPane();
final BorderPane bp2 = new BorderPane();
System.out.println("bp1 "+bp1);
System.out.println("bp2 "+bp2);
final Button button = new Button("CLICK ME");

button.parentProperty().addListener(new ChangeListener<Parent>() {
  @Override
  public void changed(ObservableValue<? extends Parent> observableValue, Parent parent, Parent parent2) {
    System.out.println("changed");
    System.out.println(button.getParent());
  }
});

bp1.centerProperty().addListener(new InvalidationListener() {
  @Override
  public void invalidated(Observable observable) {
    System.out.println("bp1 center invalidated ");
  }
});
bp2.centerProperty().addListener(new InvalidationListener() {
  @Override
  public void invalidated(Observable observable) {
    System.out.println("bp2 center invalidated ");
  }
});
// bp1.centerProperty().addListener(new ChangeListener<Node>() {
//   @Override
//   public void changed(ObservableValue<? extends Node> observableValue, Node node, Node node2) {
//      System.out.println("bp1 center changed "+node+" -> "+node2);
//    }
//  });
//  bp2.centerProperty().addListener(new ChangeListener<Node>() {
//    @Override
//    public void changed(ObservableValue<? extends Node> observableValue, Node node, Node node2) {
//      System.out.println("bp2 center changed "+node+" -> "+node2);
//    }
//  });

Scene sc1 = new Scene(bp1,100,100);
bp1.setCenter(button);
primaryStage.setScene(sc1);
primaryStage.show();

Stage stage2 = new Stage();
Scene sc2 = new Scene(bp2,100,100);
stage2.setScene(sc2);
stage2.setX(250);
stage2.show();

bp2.setCenter(button);
bp1.setCenter(button);

输出:

bp1 BorderPane@48a80c67
bp2 BorderPane@10c66375
changed
BorderPane@48a80c67[styleClass=root]
bp1 center invalidated 
changed
null
changed
BorderPane@10c66375[styleClass=root]
bp2 center invalidated 

解释:

我发现 bp1 的 center 属性没有失效,因此当按钮添加到第二个场景时没有更新。将节点添加到另一个场景通常会导致它从前一个场景中删除。但是,由于 BorderPane 使用一种特殊的方式来保存其值(center、left 等的对象属性),因此在将按钮添加到第二个场景后,按钮不会从 BorderPane 的 center 属性中删除。在同一个 BorderPane 上再次设置按钮不会将该按钮添加到其子节点,因为它认为它已被设置为中心节点。

对于你的第二个问题:

是的,每个舞台/场景只有一个场景图。

于 2013-11-05T13:34:12.097 回答