英文:
How to detect mouse-dragged event on SplitPane Divider in JavaFX
问题
我正在使用JavaFx中的SplitPane
来分割两个节点,并使用一个分隔符。我正在寻找一种区分两种情况的方法。一种情况是在屏幕宽度变化时,分隔符会响应性地移动,第二种情况是当我使用鼠标将分隔符拖动到特定位置时。我需要在使用鼠标拖动分隔符时向其添加监听器。我该如何做到这一点?
英文:
I'm using SplitPane
in JavaFx to split two nodes with a divider. I am looking for a way to differentiate between two cases. One case when the divider is moving responsively on screen width changes, second case is when I'm using the mouse to drag the divider to a certain position. I need to add a listener to the divider when it's dragged using the mouse. How can I do that?
答案1
得分: 2
以下是翻译好的内容:
你需要的是一种方式来判断分隔条位置的变化是否是窗口调整大小的结果。或者更正式地说,是场景大小调整的结果。
你可以在场景进行布局时设置一个标志,使用 addPreLayoutPulseListener 方法,然后在调整大小事件处理结束时清除该标志,使用 Platform.runLater 方法。当该标志为 true 时,你可以假定分隔条位置的任何变化都是由于场景布局,而不是用户操作引起的。
以下是一个示例:
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);
}
}
英文:
What you need is a way to know when the change in divider position is the result of a window resize. Or, more formally, a Scene resize.
You can set a flag whenever the Scene is doing a layout, using addPreLayoutPulseListener, then clear that flag at the end of resize event processing using Platform.runLater. While that flag is true, you can assume any change in SplitPane divider position was due to the Scene layout, not due to user actions.
Here’s an example:
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);
}
}
}
Note that addPreLayoutPulseListener
was added as of JavaFX 9, and isn’t available in older versions.
Java 8
For older versions of JavaFX, you can accomplish the same thing by overriding the layoutChildren() method of your Scene’s root:
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论