JavaFX:滚动窗格不适合父级容器

6
我希望创建以下场景:
+-----------------------------------------------+
|ROOT (=BorderPane)                             |
|                                               |
| +-------------------------------------------+ |
| |TOOL BAR                                   | |
| |(north)                                    | |
| +-------------------------------------------+ |
|                                               |
| +-------------------------------------------+ |
| |MyConfigurationComponent extends BorderPane| |
| |(center)                                   | |
| |  +-------------------------+  +---------+ | |
| |  |ScrollPane               |  |         | | |
| |  |(center)                 |  |         | | |
| |  | +---------------------+ |  |         | | |
| |  | |                     | |  |         | | |
| |  | |                     | |  |  SIDE   | | |
| |  | |       CANVAS        | |  |  PANE   | | |
| |  | |                     | |  | (right) | | |
| |  | |                     | |  |         | | |
| |  | |                     | |  |         | | |
| |  | +---------------------+ |  |         | | |
| |  |                         |  |         | | |
| |  +-------------------------+  +---------+ | |
| |                                           | |
| +-------------------------------------------+ |
|                                               |
+-----------------------------------------------+

期望

我希望ScrollPane尽可能地大。也就是说,ScrollPane应该能够增长并充满整个区域,无论场景的大小是多少。

由于TOOL BARSIDE PANE的宽度和高度都是固定的(首选),因此我认为ScrollPane会拉伸并填充整个剩余区域。

实际行为

但事实并非如此。ScrollPane以某种方式神奇地将其最小大小设置为大约40x40像素。高度被拉伸以匹配SIDE PANEL的高度,但宽度仍然保持不变,似乎没有任何东西可以改变它。

实际上,唯一能使ScrollPane变大的方法是显式地将minWidth设置为某个值(如400)。但这并不能解决ScrollPane的自动调整大小问题。

当我将背景颜色设置为MyConfigurationComponent时,我可以看到背景颜色按预期填充整个区域(因此问题不在于MyConfigurationComponent)。它看起来像它的中心子项(ScrollPane)被呈现为左侧,它的右侧子项(SIDE PANEL)被呈现为中心,因为右侧剩余区域仍然保持空白(但有背景,所以它仍然是MyConfigurationComponent!)。

我尝试过的方法

  • ScrollPaneminprefmax大小设置为特定值
  • 将首选大小绑定到父级的大小
  • fitToWidthfitToHeight设置为true
  • 使用AnchorPane将ScrollPane包装起来,并将其固定在四个方向
  • 使用VBox将ScrollPane包装,将优先级设置为always

当前解决方法

MyConfigurationComponent的宽度减去SIDE PANEL的宽度与ScrollPane绑定。这样做有很多问题。

代码

ROOT.fxml

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.upol.fapapp.cfa.gui.frame.FxCFAConfigFrameController">
   <top>
            <ToolBar>
                <Button text="Some button" />
            </ToolBar>
   </top>
   <center>
      <MyConfigurationComponent fx:id="configComp" />
   </center> 
</BorderPane>

MyConfigurationComponent.fxml

<BorderPane xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
    <center>
        <ScrollPane fx:id="scrollPane">
            <content>
                <Canvas width="2000" height="2000" />
            </content>
        </ScrollPane>
    </center>
    <right>
        <VBox prefWidth="100.0" BorderPane.alignment="CENTER_RIGHT">
            <children>
                <Label text="Colors" />
                <ComboBox fx:id="cmbColors" prefWidth="100.0" />    
                <!-- ... -->
                <Separator prefHeight="15.0" prefWidth="100.0" />
                <Button mnemonicParsing="false" text="Action 1" />
                <Button mnemonicParsing="false" text="Action 2" />
            </children>
        </VBox>
    </right>
</BorderPane>

问题

  • BorderPane的中心会扩展其大小以填充内容,是吗?
  • 这可能是由于BorderPane内部的BorderPane引起的吗?
  • 是否有比“我的解决方法”更好的解决方案?

能否使用AnchorPane代替BorderPane作为MyConfigurationComponent的父级?这样,您可以在打开的ScrollPane标签中使用FXML AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="100.0" AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0",其中.rightAnchor被分配给“侧面板”的宽度。 - jseashell
javadoc中得知:顶部和底部的子节点将被调整为其首选高度,并延伸到边框窗格的宽度。左侧和右侧的子节点将被调整为其首选宽度,并延伸到顶部和底部节点之间的长度。中心节点将被调整大小以填充中间的可用空间。 BorderPane不是期望行为的正确布局。使用HBox并为BorderPane和侧面窗格设置hgrow分别为ALWAYSNEVER - fabian
我完全复制并粘贴了您的FXML(只做了最少的修改以使其能够运行;即将<MyConfigurationComponent>替换为<fx:include>,删除了控制器等),它按预期工作:滚动窗格填充了未被工具栏或右侧VBox占用的空间。因此,导致它无法按您想要的方式工作的原因在于代码的其他地方。请将问题中的代码扩展为[MCVE]。 - James_D
我怀疑问题出在你实现MyConfigurationComponent类的方式上。通常,如果您使用自己的节点子类,并在FXML中执行该节点的布局,则应使用此技术。但是,由于您在MyConfigurationComponent的FXML中没有<fx:root>,因此您显然正在做其他事情。我猜测这就是问题所在。 - James_D
2个回答


0

你可以将这段代码放在你的程序中,放在 start 方法里:

stage.widthProperty().addListener(event -> {
    scrollPane.setPrefWidth(stage.getWidth());
});

stage.heightProperty().addListener(event -> {
    scrollPane.setPrefHeight(stage.getHeight());
});

如果那样不起作用,我建议将BorderPane的宽度和高度设置为舞台的尺寸:
stage.widthProperty().addListener(event -> {
    scrollPane.setPrefWidth(stage.getWidth());
    borderPane.setPrefWidth(stage.getWidth());
});

stage.heightProperty().addListener(event -> {
    scrollPane.setPrefHeight(stage.getHeight());
    borderPane.setPrefHeight(stage.getHeight());
});

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