JavaFX:FXML:如何让孩子扩展其大小以适应父窗格?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22270994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:38:29  来源:igfitidea点击:

JavaFX: FXML: How to make the child to extend its size to fit the parent pane?

javajavafx-2fxml

提问by Dean Chiu

I have managed to load a child fxml(sub UI) under a parent fxml (mainMenu UI). I have created an AnchorPane with id "mainContent". This pane is bound to 4 sides and changes in accords to the stage.

我设法在父 fxml(mainMenu UI)下加载了一个子 fxml(子 UI)。我创建了一个 ID 为“mainContent”的 AnchorPane。此窗格绑定到 4 个边,并根据舞台变化。

The child window will be loaded into the "mainContent" anchorpane. However, I can't figure out how to make the child to change along with its parent "mainContent".

子窗口将被加载到“mainContent”锚面板中。但是,我不知道如何让孩子与其父“mainContent”一起改变。

My child UI is called like this.

我的孩子 UI 就是这样调用的。

@FXML
private void mnuUserLevel_onClick(ActionEvent event) {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("DBedit.fxml"));
    loader.setController(new DBeditEntityUserlevel());

    try {
           Node n = (Node)loader.load();
           mainContent.getChildren().add(n);
    } catch (IOException e){
           System.out.println(e.getMessage());
    }
}

To further illustrate my question, please see my snap shot. The red square is the child. The yellow square is the "mainContent" AnchorPane of the MainMenu parent.

为了进一步说明我的问题,请参阅我的快照。红色方块是孩子。黄色方块是 MainMenu 父级的“mainContent”AnchorPane。

enter image description here

在此处输入图片说明

采纳答案by Sascha B

If you set the staticmethods setTopAnchor( child, value ), setBottomAnchor( ... ), setLeftAnchor( ... ), setRightAnchor( ... )of class AnchorPaneto 0.0, the child Nodewill get stretched to the full extend of the parent AnchorPane.

如果设置static方法setTopAnchor( child, value )setBottomAnchor( ... )setLeftAnchor( ... )setRightAnchor( ... )AnchorPane0.0,孩子Node会被拉伸到全延长父AnchorPane

Documentation Link: AnchorPane

文档链接:AnchorPane

edit: in the documentation link you can also see how you can set these values in your java code.

编辑:在文档链接中,您还可以看到如何在 Java 代码中设置这些值。

FXML example:

FXML 示例:

<AnchorPane fx:id="mainContent" ...>
<StackPane fx:id="subPane" AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" ></StackPane>
</AnchorPane>

回答by EthanP

If you have a Region, which is a subclassof Nodethat includes Axis, Chart, Control, and Pane(this probably includes anything you might want to load), you can bindthe child's size to the space in the parent similar to how they did here. Now any future adjustments of the parent's size will be reflected in the child.

如果你有一个Region,这是一个子类Node是包括AxisChartControl,和Pane(这可能包括你可能想负载任何东西),你可以绑定孩子的大小类似他们是如何做家长的空间在这里。现在,未来对父级大小的任何调整都将反映在子级中。

Region n = (Region)loader.load();
mainContent.getChildren().add(n);
n.prefWidthProperty().bind(mainContent.widthProperty());
n.prefHeightProperty().bind(mainContent.heightProperty());

回答by mike_s

With the look at the structure of your interface I guess you better use BorderPane as your parent container with this suggestion don't use AnchorPane directly inside the BorderPane container here is my suggestion you do:

看看你的界面结构,我猜你最好使用 BorderPane 作为你的父容器,这个建议不要直接在 BorderPane 容器内使用 AnchorPane,这是我的建议:

->BorderPane-Top = "your menu"

->BorderPane-Top = "你的菜单"

->BorderPane-Center = another container (could be SplitPane, another BorderPane etc.. but not AnchorPane I guess but you can try if you want)

->BorderPane-Center = 另一个容器(可能是 SplitPane、另一个 BorderPane 等。但我猜不是 AnchorPane 但如果你愿意,你可以尝试)

->BorderPane-Bottom = another container (could be hbox with buttons or label for info or notifications etc..)

->BorderPane-Bottom = 另一个容器(可以是带有按钮或标签的 hbox,用于信息或通知等。)

回答by blumberk1990

You could try with setting prefWidth. I don't know why, but it seems like it takes the prefWidth which is set in SceneBuilder after referencing your newPane to your AnchorPane.

您可以尝试设置 prefWidth。我不知道为什么,但在将 newPane 引用到 AnchorPane 之后,它似乎需要在 SceneBuilder 中设置的 prefWidth。

Node newPane = FXMLLoader.load(getClass().getResource("view/YourPane.fxml"));
List<Node> parentChildren = ((Pane)yourAnchorPaneId.getParent()).getChildren();
parentChildren.set(parentChildren.indexOf(yourAnchorPaneId), newPane);
yourAnchorPaneId.setPrefWidth(1800); // 1800 just example value for test
Main.primaryStage.setWidth(500); // 500 example value with which you wishe to start app

回答by Developer

Method 1 :

方法一:

// @FXML private AnchorPane pnlContainer;

FXMLLoader loader = new FXMLLoader(getClass().getResource("Demo.fxml"));

Node _node = loader.load();

_node.prefWidth(pnlContainer.widthProperty().doubleValue());
_node.prefHeight(pnlContainer.heightProperty().doubleValue());

// container child clear
pnlContainer.getChildren().clear();

// new container add
pnlContainer.getChildren().add(_node);

Alternative method;

替代方法;

FXMLLoader loader = new FXMLLoader(getClass().getResource("Demo.fxml"));

Node _node = loader.load();

AnchorPane.setTopAnchor(_node, 0.0);
AnchorPane.setRightAnchor(_node, 0.0);
AnchorPane.setLeftAnchor(_node, 0.0);
AnchorPane.setBottomAnchor(_node, 0.0);

// container child clear
pnlContainer.getChildren().clear();

// new container add
pnlContainer.getChildren().add(_node);

Method 2 detail link : JavaFX Panel inside Panel auto resizing

方法 2 详细链接:面板内的 JavaFX 面板自动调整大小

回答by mike rodent

I don't think the accepted answer is the right one. Setting the anchors in an AnchorPanedoes what it says in the documentation(setBottomAnchor):

我不认为接受的答案是正确的。在 anAnchorPane中设置锚点会按照文档( setBottomAnchor)中的说明进行操作

If set, the anchorpane will maintain the child's size and position so that its bottom is always offset by that amount from the anchorpane's bottom content edge.

如果设置,锚窗格将保持子级的大小和位置,以便其底部始终从锚窗格的底部内容边缘偏移该量。

But that's not what is desired. It is to arrange things so that the child and parent are the same size.

但这不是我们想要的。就是把东西安排得让孩子和父母的大小一样。

The important thing to appreciate, from my experiments, is that a parent Nodewill accept and adapt to the width and height (preferred width? preferred height?) of its child/children... if you tell it to. In other words, the mechanism works in the contrary direction to the one you might assume: the parent can be told to adapt to the child, not the child to the parent.

根据我的实验,要领会的重要一点是,父母Node会接受并适应其孩子/孩子的宽度和高度(首选宽度?首选高度?)...如果你告诉它。换句话说,该机制的运作方向与您可能假设的相反:可以告诉父母去适应孩子,而不是孩子去适应父母。

With an HBoxcontaining a ScrollPanecontaining an AnchorPanecontaining a TextArea, using SceneBuilder, this does what the question is looking for:

使用HBox包含一个ScrollPane包含一个AnchorPane包含一个 TextArea,使用 SceneBuilder,这就是问题所要寻找的:

  <HBox prefHeight="100.0" prefWidth="200.0">
     <children>
        <ScrollPane prefHeight="100.0">
          <content>
            <AnchorPane>
                 <children>
                    <TextArea fx:id="logTextArea" prefWidth="800.0">
                    </TextArea>
                 </children>
              </AnchorPane>
          </content>
        </ScrollPane>
     </children>
  </HBox>

Note that there is no use of anchors, and above all that the ScrollPaneand the AnchorPanehave no "preferred width" setting.

请注意,没有使用锚点,最重要的是ScrollPaneAnchorPane没有“首选宽度”设置。

In SceneBuilder, the thing to adjust here for the ScrollPaneand the AnchorPaneis in the right-hand panel/concertina, under "Layout: ...:" choose the ScrollPane, and set "Pref Width" to "USE_COMPUTED_AREA". Then choose the AnchorPaneand do the same. Finally, choose the TextAreaand set this to your choice, e.g. in my case 800 (pixels). Obviously this setting can be adjusted to something more sophisticated in your code if you want.

在 SceneBuilder 中,此处要调整ScrollPane和 的AnchorPane内容位于右侧面板/六角手风琴中,在“布局:...:”下选择ScrollPane,并将“Pref Width”设置为“USE_COMPUTED_AREA”。然后选择AnchorPane并执行相同的操作。最后,选择TextArea并将其设置为您的选择,例如在我的情况下为 800(像素)。显然,如果您愿意,可以将此设置调整为代码中更复杂的内容。

You will then see that the parent Nodeof the TextArea(AnchorPane) and grandparent Node(ScrollPane) adjust to accommodate the TextArea.

然后您将看到( ) 和祖父母( )的父级Node进行调整以适应.TextAreaAnchorPaneNodeScrollPaneTextArea

Note that the prefWidthsetting of the HBoxthen gets ignored. It is the normal job of a container like an HBoxto accommodate its descendants, and it would only be if you set its maxWidthto something incompatible with the requirements of its descendants that that constraint would then apply.

请注意,then的prefWidth设置将HBox忽略HBox容纳其后代是容器的正常工作,只有当您将其设置maxWidth为与其后代的要求不兼容的内容时,该约束才会应用。

If you set a grandchild Nodelike this with a prefWidthof 800, I assume there is some way of calculating the width, under normal circumstances, of the grandparent ScrollPane: this will be something to do with settings of borders, padding, margins and the like, in all three components involved. Note the protectedmethod in class Region, computePrefWidth, intended for subclasses to override, which may be of interest.

如果设置一个孙子Node这样用prefWidth的800,我认为有计算的宽度,一般情况下,祖父的一些方法ScrollPane:这将是事做边框,填充,边距的设置等,在所有三个组件都涉及。请注意protectedclass Region, 中的方法computePrefWidth,旨在供子类覆盖,这可能很有趣。

Plus, in the case of ScrollPane, the presence or absence of vertical and/or horizontal scrollbars, as and when these appear. If you set wrapTextto trueon the TextAreayou might hope that a horizontal scrollbar will never appear. My experiments seem to show that you also need to set ScrollPane's fitToWidthPropertyto true.

另外,在 的情况ScrollPane下,垂直和/或水平滚动条的存在与否,当它们出现时。如果您设置wrapTexttrueonTextArea您可能希望永远不会出现水平滚动条。我的实验似乎表明您还需要将ScrollPane's设置fitToWidthPropertytrue.