0

我正在尝试找到一种方法来防止分隔线位置在其中一个分隔线受 maxWidth 属性约束时发生变化。

在示例中,我单击一个按钮以最小化面板,并希望调整中央面板的大小以容纳额外的可用空间,但额外的空间在其他两个面板之间共享。

运行中的应用

单击左键后,右分隔线已移动

    @Override
public void start(Stage stage) {
    BooleanProperty clicked1 = new SimpleBooleanProperty(false);
    BooleanProperty clicked2 = new SimpleBooleanProperty(false);

    Button button1 = new Button("Click");
    button1.setOnAction(event -> clicked1.set(!clicked1.get()));
    button1.setMaxWidth(800);

    Button button2 = new Button("Click");
    button2.setOnAction(event -> clicked2.set(!clicked2.get()));
    button2.setMaxWidth(800);

    StackPane pane1  = new StackPane(button1);
    StackPane pane2 = new StackPane();
    StackPane pane3  = new StackPane(button2);

    pane1.maxWidthProperty().bind(Bindings.createDoubleBinding(() -> clicked1.get() ? 40.0 : Double.MAX_VALUE, clicked1));
    pane3.maxWidthProperty().bind(Bindings.createDoubleBinding(() -> clicked2.get() ? 40.0 : Double.MAX_VALUE, clicked2));

    SplitPane splitPane = new SplitPane(pane1, pane2, pane3);
    splitPane.setPrefSize(600, 400);
    SplitPane.setResizableWithParent(pane1, false);
    SplitPane.setResizableWithParent(pane3, false);
    splitPane.setDividerPositions(0.25, 0.75);

    stage.setScene(new Scene(splitPane));
    stage.show();
}
4

1 回答 1

0

您的问题的解决方案是根据修改后的窗格宽度计算和设置分隔线位置。

请在下面找到此逻辑的代码。包括关于做什么的内联评论。

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SplitPaneIssue extends Application {

    private double COMPRESSED_WIDTH = 40.0;
    private double D1_DEFAULT_POSITION = 0.25;
    private double D2_DEFAULT_POSITION = 0.75;

    @Override
    public void start(Stage stage) {
        BooleanProperty clicked1 = new SimpleBooleanProperty();
        BooleanProperty clicked2 = new SimpleBooleanProperty();

        Button button1 = new Button("Click");
        button1.setOnAction(event -> clicked1.set(!clicked1.get()));
        button1.setMaxWidth(Double.MAX_VALUE);

        Button button2 = new Button("Click");
        button2.setOnAction(event -> clicked2.set(!clicked2.get()));
        button2.setMaxWidth(Double.MAX_VALUE);

        StackPane pane1 = new StackPane(button1);
        StackPane pane2 = new StackPane();
        StackPane pane3 = new StackPane(button2);

        SplitPane splitPane = new SplitPane(pane1, pane2, pane3);
        splitPane.setPrefSize(600, 400);
        SplitPane.setResizableWithParent(pane1, false);
        SplitPane.setResizableWithParent(pane3, false);
        splitPane.setDividerPositions(D1_DEFAULT_POSITION, D2_DEFAULT_POSITION);

        clicked1.addListener((obs, old, val) -> {
            // First compute the total width of all panes and the percentage value per pixel
            double percentPerPx = 1 / (pane1.getWidth() + pane2.getWidth() + pane3.getWidth());
            // Set the max width based on the toggle value
            pane1.setMaxWidth(val ? COMPRESSED_WIDTH : Double.MAX_VALUE);

            // Now compute the divider positions with the new width.
            double d1 = val ? COMPRESSED_WIDTH * percentPerPx : D1_DEFAULT_POSITION;
            // Computing the width percentage for the pane3 and subtracting from 1 will retain its position.
            double d2 = 1 - (pane3.getWidth() * percentPerPx);
            splitPane.setDividerPositions(round(d1), round(d2));
        });
        clicked2.addListener((obs, old, val) -> {
            double percentPerPx = 1 / (pane1.getWidth() + pane2.getWidth() + pane3.getWidth());
            pane3.setMaxWidth(val ? COMPRESSED_WIDTH : Double.MAX_VALUE);
            double d1 = pane1.getWidth() * percentPerPx;
            double d2 = val ? 1 - (COMPRESSED_WIDTH * percentPerPx) : D2_DEFAULT_POSITION;
            splitPane.setDividerPositions(round(d1), round(d2));
        });
        stage.setScene(new Scene(splitPane));
        stage.show();
    }

    private double round(double value) {
        long factor = (long) Math.pow(10, 2);
        value = value * factor;
        long tmp = Math.round(value);
        return (double) tmp / factor;
    }
}
于 2021-03-11T22:08:25.403 回答