如何在 JavaFX 中的 SplitPane Divider 上检测鼠标拖动事件
How to detect mouse-dragged event on SplitPane Divider in JavaFX
我在 JavaFx 中使用 SplitPane
用分隔符拆分两个节点。我正在寻找一种方法来区分两种情况。一种情况是当分隔线响应屏幕宽度变化而移动时,第二种情况是当我使用鼠标将分隔线拖动到某个位置时。使用鼠标拖动时,我需要向分隔线添加一个侦听器。我该怎么做?
您需要一种方法来了解分隔符位置的变化何时是 window 调整大小的结果。或者,更正式地说,场景调整大小。
您可以在场景进行布局时设置标志,使用addPreLayoutPulseListener, then clear that flag at the end of resize event processing using 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 开始添加的,在旧版本中不可用。
Java 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);
}
}
我在 JavaFx 中使用 SplitPane
用分隔符拆分两个节点。我正在寻找一种方法来区分两种情况。一种情况是当分隔线响应屏幕宽度变化而移动时,第二种情况是当我使用鼠标将分隔线拖动到某个位置时。使用鼠标拖动时,我需要向分隔线添加一个侦听器。我该怎么做?
您需要一种方法来了解分隔符位置的变化何时是 window 调整大小的结果。或者,更正式地说,场景调整大小。
您可以在场景进行布局时设置标志,使用addPreLayoutPulseListener, then clear that flag at the end of resize event processing using 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 开始添加的,在旧版本中不可用。
Java 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);
}
}