简体   繁体   English

JavaFX 2 BorderPane使用完整空间

[英]JavaFX 2 BorderPane Use Full Space

I´m just facing a little issue that I can´t solve by myself. 我只是面临一个我自己无法解决的小问题。 I try to place a vBox including a TextField and a HTML-Editor in my BorderPane, but the full space is not used. 我尝试在BorderPane中放置一个包含TextField和HTML-Editor的vBox,但是没有使用全部空间。 Another problem is that if I shrink the window, the html-editor overlaps with my left option window. 另一个问题是,如果我缩小窗口,则html编辑器将与我的左选项窗口重叠。

在此处输入图片说明

private void initEditor()
{
editor = new HTMLEditor();
editor.setId("editor");
editor.lookup(".top-toolbar").setDisable(true);
editor.lookup(".top-toolbar").setManaged(false);
((ToolBar) editor.lookup(".bottom-toolbar")).getItems().addAll(FXCollections.observableArrayList(((ToolBar)editor.lookup(".top-toolbar")).getItems()));

editorBox = new VBox();
TextField field = new TextField();
field.setPrefHeight(36);
field.setId("editor-title");
editorBox.setFillWidth(true);
editorBox.getChildren().addAll(field, editor);
    root.setCenter(editorBox);
}

OK, so a few things going wrong here, I'll try to address them provide some advice and a sample solution. 好的,因此这里有些错误,我将尝试为它们提供一些建议和示例解决方案。

I try to place a vBox including a TextField and a HTML-Editor in my BorderPane, but the full space is not used. 我尝试在BorderPane中放置一个包含TextField和HTML-Editor的vBox,但是没有使用全部空间。

You need to use the VBox.setVgrow(editor, Priority.ALWAYS) method to get the HTMLEditor to take up any extra space in the VBox. 您需要使用VBox.setVgrow(editor,Priority.ALWAYS)方法来获取HTMLEditor来占用VBox中的任何额外空间。 Also, make sure that the HTMLeditor has an unbounded max height so that it can grow to fit the available area, for example editor.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE) . 另外,请确保HTMLeditor具有不受限制的最大高度,以便可以增长以适合可用区域,例如editor.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE) Calling editorBox.setFillWidth(true) is redundant as the default value for the fillWidth property is true . 调用editorBox.setFillWidth(true)是多余的,因为fillWidth属性的默认值为true

But even if you do all that, (as of 2.2b13) there is a bug in WebPane sizing which will cause you problems. 但是,即使您做了所有这些工作(从2.2b13开始),WebPane大小调整中仍然存在一个错误,这会给您带来麻烦。 Internally the WebPane is implemented as a GridPane containing the Toolbar and an editable WebView. 在内部,WebPane被实现为GridPane,其中包含工具栏和可编辑的WebView。 By default, WebView has a preferred size of 800x600. 默认情况下,WebView的首选大小为800x600。 The HtmlEditor control does not set the GridPane constraints for the WebView to allow it to be sized past it's preferred size. HtmlEditor控件未为WebView设置GridPane约束以允许其大小超过其首选大小。

To work around this, you can lookup the WebView via a css lookup after it has been added to an active Scene and adjust the GridPane constraints manually. 要解决此问题,您可以在将WebView添加到活动场景中之后通过CSS查找来查找该WebView,并手动调整GridPane约束。 Here is some code to do that: 这是执行此操作的一些代码:

stage.show();
...
WebView webview = (WebView) editor.lookup("WebView");
GridPane.setHgrow(webview, Priority.ALWAYS);
GridPane.setVgrow(webview, Priority.ALWAYS);

I shrink the window, the html-editor overlaps with my left option window. 我缩小窗口,html编辑器与我的左选项窗口重叠。

Explicitly set the minimum width setting for the center pane in your BorderPane so that it won't overflow over the outer edge Panes. 在BorderPane中明确设置中心窗格的最小宽度设置,以使其不会溢出到外部边缘窗格上。

editorBox.setMinSize(0, 0);

You need to do this because the BorderPane documentation states: 您需要这样做,因为BorderPane文档指出:

BorderPane does not clip its content by default, so it is possible that childrens' bounds may extend outside its own bounds if a child's min size prevents it from being fit within it space. BorderPane默认情况下不会裁剪其内容,因此,如果孩子的最小尺寸使其无法适应其空间,则孩子的边界可能会超出其自身的边界。


As an aside the lookup calls in your code are suspicious. 顺便说一句,代码中的查找调用是可疑的。 Normally you can't lookup nodes by css ID until the node has been added to an active scene on a displayed stage and the JavaFX system has had a chance to run a CSS layout pass on the node - otherwise the lookup will just return null. 通常,您无法通过CSS ID查找节点,直到将该节点添加到显示的舞台上的活动场景并且JavaFX系统有机会在该节点上运行CSS布局遍历为止-否则查找将仅返回null。


For debugging JavaFX layout issues, the ScenicView application is invaluable. 对于调试JavaFX布局问题, ScenicView应用程序非常宝贵。


Here is a complete example to generate a layout similar to the image linked in your question, but without the issues you mention. 这是一个完整的示例,用于生成与您的问题中链接的图像相似的布局,但没有提及您遇到的问题。

import com.javafx.experiments.scenicview.ScenicView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.web.*;
import javafx.stage.*;

public class HtmlEditorInBorderPane extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(final Stage stage) throws IOException {
    // option pane.
    VBox optionPane = new VBox(10);
    MenuBar menuBar = new MenuBar();
    menuBar.getMenus().addAll(new Menu("School"), new Menu("Social"), new Menu("Network"));
    TreeItem<String> root = new TreeItem<>("Private Notes");
    root.setExpanded(false);
    root.getChildren().addAll(new TreeItem<>("Layout"), new TreeItem<>("is not"), new TreeItem<>("easy"));
    TreeView<String> notes = new TreeView<>(root);
    optionPane.getChildren().addAll(menuBar, new Label("Kaiser Notes"), notes);
    optionPane.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");

    // editor pane.
    HTMLEditor editor = new HTMLEditor();
    VBox editorBox = new VBox(10);
    TextField textField = new TextField();
    editorBox.getChildren().addAll(textField, editor);
    editorBox.setStyle("-fx-background-color: mistyrose; -fx-padding: 10;");
    editor.setHtmlText(getSampleText());

    // option layout constraints
    VBox.setVgrow(notes, Priority.ALWAYS);

    // editor layout constraints
    textField.setMinHeight(Control.USE_PREF_SIZE); // stop the textfield from getting squashed when the scene is sized small.
    VBox.setVgrow(editor, Priority.ALWAYS);        // tells the editor to fill available vertical space.
    editorBox.setMinSize(0, 0);                    // stops the editor from overflowing it's bounds in a BorderPane.

    // layout the scene.
    BorderPane layout = new BorderPane();
    layout.setLeft(optionPane);
    layout.setCenter(editorBox);
    stage.setScene(new Scene(layout));
    stage.show();

    // addition of static layout grow constraints for the htmleditor embedded webview.
    WebView webview = (WebView) editor.lookup("WebView");
    GridPane.setHgrow(webview, Priority.ALWAYS);  // allow the webview to grow beyond it's preferred width of 800.
    GridPane.setVgrow(webview, Priority.ALWAYS);  // allow the webview to grow beyond it's preferred height of 600.
  }

  // get some dummy lorem ipsum sample text.
  private String getSampleText() throws IOException {
    StringBuilder builder = new StringBuilder();
    try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL("http://www.lorem-ipsum-text.com/").openStream()))) {
      String string;
      while ((string = in.readLine()) != null) {
        builder.append(string);
      }
    }
    return builder.toString();
  }
}
    GridPane gridPane = (GridPane) editor.getChildrenUnmodifiable().get(0);
    RowConstraints row1 = new RowConstraints();
    row1.setVgrow(Priority.NEVER);
    RowConstraints row2 = new RowConstraints();
    row2.setVgrow(Priority.NEVER);
    RowConstraints row3 = new RowConstraints();
    row3.setVgrow(Priority.ALWAYS);
    gridPane.getRowConstraints().addAll(row1, row2, row3);

How to set and resize ScrollPane with FXML: 如何使用FXML设置ScrollPane并调整其大小:

package anchorscroll;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;

public class FXMLDocumentController implements Initializable {

    private Label label;
    @FXML
    private VBox vp;
    @FXML
    private ScrollPane sp;
    @FXML

    private Pane panel;
    @FXML
    private double Width;
    @FXML
    private double Height;

    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        label.setText("Hello World!");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
        Width = panel.getWidth();
        Height = panel.getHeight();
        sp.setPrefWidth(Width - 60);
        sp.setPrefHeight(Height - 60);

        panel.widthProperty().addListener(p -> {
            Width = panel.getWidth();
            Height = panel.getHeight();
            System.out.println("Width " + Width + " Height " + Height);
            sp.setPrefWidth(Width - 60);
            sp.setPrefHeight(Height - 60);
        });

        panel.heightProperty().addListener(p -> {
            Width = panel.getWidth();
            Height = panel.getHeight();
            System.out.println("Width " + Width + " Height " + Height);
            sp.setPrefWidth(Width - 60);
            sp.setPrefHeight(Height - 60);
        });

        VBox v = new VBox();
        for (int i = 0; i < 100; i++) {
            v.getChildren().add(new Button("Hello " + i));
        }
        sp.setContent(v);

        VBox p = new VBox();
        try {
            p = FXMLLoader.load(getClass().getResource("NewMessage.fxml")); // "/fxml/Register.fxml"
            sp.setContent(p);
        } catch (IOException ex) {
            Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}

!!! !!! NewMessage.fxml need start with VBox panel !!! NewMessage.fxml需要从VBox面板开始!

Comment or delete this 2 lines if u don't need load FXML: 如果您不需要加载FXML,请注释或删除以下两行:

p = FXMLLoader.load(getClass().getResource("NewMessage.fxml"));
sp.setContent(p);

And layout: 和布局:

<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<Pane fx:id="panel" prefHeight="400.0" prefWidth="600.0" stylesheets="@Styles.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="anchorscroll.FXMLDocumentController">
    <children>
        <HBox prefHeight="60.0" prefWidth="600.0">
            <children>
                <Label text="Label" />
            </children>
        </HBox>
        <VBox fx:id="vp" layoutY="60.0" prefHeight="540.0" prefWidth="60.0">
            <children>
                <Button mnemonicParsing="false" prefWidth="50.0" text="Button" />
            </children>
        </VBox>
        <ScrollPane fx:id="sp" fitToHeight="true" fitToWidth="true" layoutX="60.0" layoutY="60.0" prefHeight="340.0" prefWidth="540.0" vbarPolicy="ALWAYS" />
    </children>
</Pane>

Layout image (topBar, leftBar, scrollContentPane) 布局图像(topBar,leftBar,scrollContentPane)

I was also facing the same kind of issue. 我也面临着同样的问题。 My anchorPane inside borderPane was not filling up. 我的borderPane内部的anchorPane没有装满。 Setting a large number for prefSize worked for me. 为prefSize设置一个较大的值对我有用。 So when border pane grows, it tries to provide as much size as possible to its child 因此,当边框窗格增大时,它将尝试为其子级提供尽可能大的尺寸

anchorPane.setMinSize(25, 25);
anchorPane.setPrefSize(25000, 25000);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM