Sai*_*dem 5 javafx splitpane flowpane
如果内容具有多行 FlowPane,我会遇到 SplitPane 分隔符的问题。如果 FlowPane 在一行中呈现,则没有问题。如果 FlowPane 有多于一行,则内容部分会发生变化。
行数越多,移位越大。
为了演示这个问题,下面是一个快速演示。该演示包含三个垂直 splitPane,其中每个 SplitPane 都有不同编号的 FlowPane。行数。(第一个 splitPane - 1 行,第二个 SplitPane - 2 行,第三个 SplitPane - 3 行)
当使用 1 个 FlowPane 行调整 splitPane 大小时,没有问题,一切正常。然而,如果我调整第二个 splitPane 的大小,内容就会从所需的位置移动,从而在 SplitPane 中留下空白空间。当调整第三个 splitPane 的大小时,空间甚至更大。
我相信这应该是 SplitPane-FlowPane 计算中的一些问题(或者我也可能是错的)。但在这个阶段,我不是试图找出根本原因(这将在 JavaFX 源代码中的某个地方),而是更迫切地想通过一些解决方法来解决这个问题。
我尝试了几种方法,例如绑定高度、设置一些区域常量等,但都没有奏效。FlowPane的所有高度计算确实是正确的。
你们中的任何人对我如何解决这个问题有任何建议吗?
注意:该问题可以在所有版本的 JavaFX 中重现
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
@SuppressWarnings("javadoc")
public class SplitPaneDividerIssueDemo extends Application {
    /**
     * FlowPane for debugging purpose.
     */
    class SimpleFlowPane extends FlowPane {
        @Override
        protected double computeMaxHeight(final double width) {
            final double height = super.computeMaxHeight(width);
            // Debugging the first FlowPane in each SplitPane
            if (isFirst()) {
                System.out.println("Computed max  height for " + getId() + "  :: " + height);
            }
            return height;
        }
        @Override
        protected double computeMinHeight(final double width) {
            final double height = super.computeMinHeight(width);
            if (isFirst()) {
                System.out.println("Computed min  height for " + getId() + "  :: " + height);
            }
            return height;
        }
        @Override
        protected double computePrefHeight(final double width) {
            final double height = super.computePrefHeight(width);
            if (isFirst()) {
               System.out.println("Computed pref height for " + getId() + "  :: " + height);
            }
            return height;
        }
        private boolean isFirst() {
            return getId().endsWith("-1");
        }
    }
    private int splitId = 1;
    private int flowId = 1;
    public static void main(final String... a) {
        Application.launch(a);
    }
    @Override
    public void start(final Stage primaryStage) throws Exception {
        final HBox root = new HBox(buildSplitPane(10), buildSplitPane(20), buildSplitPane(30));
        root.setSpacing(10);
        final Scene scene = new Scene(root, 1250, 700);
        primaryStage.setScene(scene);
        primaryStage.setTitle("SplitPane Divider Issue");
        primaryStage.show();
    }
    private VBox buildContent(final int count) {
        final Button button = new Button("Button");
        final FlowPane flowPane = new SimpleFlowPane();
        flowPane.setId("flow-" + splitId + "-" + flowId);
        flowPane.setVgap(5);
        flowPane.setHgap(5);
        for (int i = 0; i < count; i++) {
            flowPane.getChildren().add(new Button("" + i));
        }
        final ScrollPane scroll = new ScrollPane();
        VBox.setVgrow(scroll, Priority.ALWAYS);
        final ToolBar toolBar = new ToolBar();
        toolBar.getItems().add(new Button("Test"));
        final VBox pane = new VBox();
        pane.setPadding(new Insets(5));
        pane.setSpacing(5);
        pane.setStyle("-fx-background-color:yellow;-fx-border-width:1px;-fx-border-color:red;");
        pane.getChildren().addAll(button, flowPane, scroll, toolBar);
        pane.parentProperty().addListener((obs,old,content)->{
            if(content!=null){
                content.layoutYProperty().addListener((obs1,old1,layoutY)->{
                    System.out.println("LayoutY of content having "+flowPane.getId()+" :: "+layoutY);
                });
            }
        });
        flowId++;
        return pane;
    }
    private SplitPane buildSplitPane(final int count) {
        final SplitPane splitPane = new SplitPane();
        splitPane.setStyle("-fx-background-color:green;");
        splitPane.setOrientation(Orientation.VERTICAL);
        splitPane.setDividerPositions(.36, .70);
        splitPane.getItems().addAll(buildContent(count), buildContent(count), buildContent(count));
        HBox.setHgrow(splitPane, Priority.ALWAYS);
        splitId++;
        flowId = 1;
        return splitPane;
    }
}
问题出在 FlowPane 的 minHeight 内,因为它是水平方向的,使得 minHeight 非常动态。它的设计似乎是随着宽度的增长和缩小而改变 minHeight 的。根据文档,当您垂直压缩父级时,VBox 会将其 minHeight 计算为“顶部/底部插图加上每个子级的最小高度加上每个子级之间的间距之和”。显然存在一些问题,FlowPane 的父级无法解释其 minHeight。
HBox 将其 minHeight 计算为“顶部/底部插图加上最大的子项最小高度”。因此,如果将 FlowPane 包装在 HBox 中,则该 HBox minHeight 将绑定到 FlowPane 的高度,然后将该 HBox 放置在 FlowPane 应该所在的 VBox 中。
HBox flowPaneContainer = new HBox();
flowPaneContainer.getChildren().add(flowPane);
pane.getChildren().addAll(button, flowPaneContainer, scroll, toolBar);
编辑:如果你的舞台尺寸是固定的,这很好。如果您的应用程序可调整大小,则需要做更多工作,因为 flowPane minHeight 将发生变化,从而更改 HBox minHeight,然后会导致相同的问题,因为每个 VBox 内的所有内容都没有足够的空间。
对于可调整大小的应用程序,我通常通过将 SplitPane 的每个部分包装在 ScrollPane 中来处理此问题。
| 归档时间: | 
 | 
| 查看次数: | 116 次 | 
| 最近记录: |