如何将舞台大小调整与组件大小调整绑定?

18

我有一个使用FXML的JavaFX 2.0 应用程序。希望在窗口大小调整时,组件(如文本输入框、下拉框、布局等)能够自动调整大小。

  • 根据Oracle JavaFX文档所述,要实现这样的效果,可以使用一些特殊的形状属性:

在使用JavaFX构建GUI应用程序时,您会注意到API中某些类已经实现了属性。例如,javafx.scene.shape.Rectangle 类包含了 arcHeightarcWidthheightwidthxy 等属性。对于每个属性,都有相应的方法与之匹配,符合之前描述的约定。例如,getArcHeight()setArcHeight(double)arcHeightProperty(),它们共同表明(对开发人员和工具)该属性存在。

  • 要向舞台添加监听器,可以执行以下操作:

   stage.resizableProperty().addListener(new ChangeListener<Boolean>(){
    @Override
    public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2){
        throw new UnsupportedOperationException("Not supported yet.");
    }

});

所以有两个问题:

  • 为了进行一些绑定,我必须在控制器类中获取我的场景(stage)。那么,我如何在控制器类中获取场景(stage)?
  • 看起来 UI 控件没有任何宽度\高度属性可以绑定到其他对象。或者我还没有找到它们。

那么,我该如何解决我的问题呢?

更新 关于 Scene Builder 对 Sergey Grinev 的回答: 当我在我的组件上使用 Ctrl+K (让它占据其父组件的整个区域) - 一切都好。

但是如果我想告诉我的组件占据50%的区域呢? 例如,我有一个选项卡,其中有两个 VBox。选项卡的宽度为100px。每个 Vbox 宽度为50px。VBox1 的 x 坐标为x1=0x2=50,而 VBox2 的 x 坐标为x1=50x2=100。 然后我调整JavaFX应用程序窗口的大小。 现在我的选项卡宽度为200px。 但是我的 Vboxes 宽度仍然是50px:VBox1 的 x1=0x2=50,而 VBox2 的x1=150x2=200。 而我需要它们分别为 VBox1 x1=0x2=100,VBox2 x1=100x2=200。其中 x1 和 x2 的值是 VBoxes 角落的坐标。

那么,Scene Builder 如何帮助我解决这个问题呢?

3个回答

21

构建可调整大小的 GUI 的一些建议 =>

  • 确保您应用程序的根是 Pane 子类,而不是 Group。
  • 取消按钮的最大尺寸限制(例如,button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE))。
  • 大多数情况下,布局面板可以为您处理调整大小,您不需要使用绑定和监听器=> 即只有在真正需要时才进行绑定。
  • UI 控件和布局面板都是 Regions => 所有的 Regions 都有只读的高度和宽度属性,您可以监听和绑定这些属性。
  • 您无法直接将控件的高度和宽度属性绑定到另一个值。相反,请使用 minWidth/Height、prefWidth/Height、maxWidth/Height 属性。
  • 场景具有高度和宽度属性,如果需要,您可以进行绑定。如果这样做,当舞台被调整大小时,场景将被调整大小,然后您绑定的组件将被调整大小。如果场景的根是布局面板而不是群组,则通常不需要进行此绑定。
  • 对于独立应用程序,如果不设置场景的高度和宽度,则场景(和舞台)将被调整大小以适应场景根节点的首选大小(通常是您想要的)。
  • 如果所有其他方法都失败,则可以开始覆盖 Parent 的 layoutchildren 方法。

这里是一个可调整大小的 JavaFX UI 示例,它实现了上述原则:an example


7
另一个简单的选择是使用JavaFX Scene Builder(最近作为公共测试版发布:http://www.oracle.com/technetwork/java/javafx/tools/index.html)。它允许您通过拖放创建UI,并将UI元素锚定到边框(使用锚定工具),因此它们会随着窗口边框的移动/调整大小而移动/调整大小。
更新:
要实现自动调整百分比布局,您可以使用带有ColumnConstraint的GridPane:
public void start(Stage stage) {

    VBox box1 = new VBox(1);
    VBox box2 = new VBox(1);

    //random content
    RectangleBuilder builder = RectangleBuilder.create().width(20).height(20);
    box1.getChildren().addAll(builder.build(), builder.build(), builder.build());
    builder.fill(Color.RED);
    box2.getChildren().addAll(builder.build(), builder.build(), builder.build());

    //half by half screen
    GridPane grid = new GridPane();
    grid.addRow(0, box1, box2);

    ColumnConstraints halfConstraint = ColumnConstraintsBuilder.create().percentWidth(50).build();
    grid.getColumnConstraints().addAll(halfConstraint, halfConstraint);

    stage.setScene(new Scene(grid, 300, 250));
    stage.show();
}

我已经以回复评论的形式更新了问题,因为我已经没有足够的字符。 - Victoria Agafonova

3

建议:

  1. 如果您只有一个主舞台,则在应用程序启动时将其存储在静态字段/变量中,并在所有控制器类中访问它。
  2. 您可以将所有控件/组件放入管理其子布局的布局/窗格中。有关不同布局,请查看API文档。之后,将舞台场景的宽度和高度属性绑定到此布局的属性上。更多关于绑定的内容请参阅使用JavaFX属性和绑定
    单向绑定的示例

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接