2

SplitPane在 JavaFx 中使用分隔线分割两个节点。我正在寻找一种区分两种情况的方法。一种情况是分隔线在屏幕宽度变化时响应移动,第二种情况是我使用鼠标将分隔线拖动到某个位置。当使用鼠标拖动分隔线时,我需要向分隔线添加一个侦听器。我怎样才能做到这一点?

4

1 回答 1

2

您需要一种方法来了解分隔线位置的变化何时是窗口调整大小的结果。或者,更正式地说,场景调整大小。

您可以在场景进行布局时使用addPreLayoutPulseListener设置一个标志,然后在调整大小事件处理结束时使用Platform.runLater清除该标志。虽然该标志为真,但您可以假设 SplitPane 分隔线位置的任何变化是由于场景布局,而不是由于用户操作。

这是一个例子:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;

public class DividerListenerTest
extends Application {
    private boolean windowResizing;

    @Override
    public void start(Stage stage) {
        Label left = new Label("Left");
        left.setMinSize(1, 1);
        left.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        left.setPadding(new Insets(200));

        Label right = new Label("Right");
        right.setMinSize(1, 1);
        right.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        right.setPadding(new Insets(200));

        SplitPane splitPane = new SplitPane(left, right);

        splitPane.getDividers().get(0).positionProperty().addListener(
            (o, oldPos, newPos) -> dividerResized(oldPos, newPos));

        Scene scene = new Scene(new BorderPane(splitPane));
        scene.addPreLayoutPulseListener(() -> {
            windowResizing = true;
            Platform.runLater(() -> {
                windowResizing = false;
            });
        });

        stage.setScene(scene);
        stage.setTitle("Divider Listener Test");
        stage.show();
    }

    private void dividerResized(Number oldPos,
                                Number newPos) {
        if (windowResizing) {
            return;
        }

        System.out.println("User moved divider position to " + newPos);
    }

    public static class Main {
        public static void main(String[] args) {
            Application.launch(DividerListenerTest.class, args);
        }
    }
}

请注意,它addPreLayoutPulseListener是从 JavaFX 9 开始添加的,在旧版本中不可用。

爪哇 8

对于旧版本的 JavaFX,您可以通过覆盖场景根的layoutChildren()方法来完成相同的操作:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;

public class DividerListenerTest
extends Application {
    private boolean windowResizing;

    @Override
    public void start(Stage stage) {
        Label left = new Label("Left");
        left.setMinSize(1, 1);
        left.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        left.setPadding(new Insets(200));

        Label right = new Label("Right");
        right.setMinSize(1, 1);
        right.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        right.setPadding(new Insets(200));

        SplitPane splitPane = new SplitPane(left, right);

        splitPane.getDividers().get(0).positionProperty().addListener(
            (o, oldPos, newPos) -> dividerResized(oldPos, newPos));

        Scene scene = new Scene(new BorderPane(splitPane) {
            @Override
            protected void layoutChildren() {
                windowResizing = true;
                super.layoutChildren();
                Platform.runLater(() -> {
                    windowResizing = false;
                });
            }
        });

        stage.setScene(scene);
        stage.setTitle("Divider Listener Test");
        stage.show();
    }

    private void dividerResized(Number oldPos,
                                Number newPos) {
        if (windowResizing) {
            return;
        }

        System.out.println("User moved divider position to " + newPos);
    }
}
于 2020-10-02T20:29:26.830 回答