受 window 大小调整影响的 JavaFX 拖动事件
JavaFX drag events affected by window resizing
我一直在尝试在 JavaFX 中实现节点拖动,我遇到了一个看起来应该相对容易解决的问题。我猜这与 window 调整大小后 JavaFX 场景图如何更新(或不更新)有关。
反正问题如下:
该应用程序以一个小的 window 开始,只有一个节点可以单击并在 window 周围拖动。这在两种情况下工作正常:
- 在调整大小之前,在 window 中单击并拖动节点。
- 调整大小后在window中单击并拖动节点。
但是第三次失败了:
- 在 window 调整大小(放大)之前和之后单击并拖动节点。
似乎拖动事件无法识别 window 边界的变化。换句话说,如果我单击并拖动节点,则放大 window。随后的点击和拖动尝试将被限制在 window 的原始范围内。
无论如何,下面是我编写的示例 JavaFX 应用程序来演示此问题。它复制了我上面描述的三个测试用例。
谢谢。
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.event.EventHandler;
public class Main extends Application {
private AnchorPane node_root;
private BorderPane mRoot;
@Override
public void start(Stage primaryStage) {
try {
node_root = new AnchorPane();
mRoot = new BorderPane();
Scene scene = new Scene(mRoot,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
addFileSystemNode ();
mRoot.setOnDragDone (new EventHandler <DragEvent>() {
@Override
public void handle(DragEvent event) {
System.out.println ("Drag done");
event.consume();
}
});
}
public static void main(String[] args) {
launch(args);
}
public final void addFileSystemNode () {
Label node_title = new Label();
node_title.setText("drag me!");
node_root.getChildren().add (node_title);
mRoot.getChildren().add (node_root);
buildNodeDragHandlers();
node_root.setLayoutX(100.0);
node_root.setLayoutY(100.0);
}
public void relocateToPoint (Point2D p) {
Point2D p2 = mRoot.sceneToLocal(p);
node_root.relocate (
(int) (p2.getX()),
(int) (p2.getY())
);
}
public void buildNodeDragHandlers() {
mRoot.setOnDragOver(new EventHandler <DragEvent>() {
//dragover to handle node dragging in the right pane view
@Override
public void handle(DragEvent event) {
System.out.println("parent node drag over" + " " + ((Pane) event.getSource()).getId());
event.acceptTransferModes(TransferMode.ANY);
relocateToPoint(new Point2D( event.getSceneX(), event.getSceneY()));
event.consume();
}
});
mRoot.setOnDragDropped(new EventHandler <DragEvent> () {
@Override
public void handle(DragEvent event) {
System.out.println("node drag dropped");
event.setDropCompleted(true);
event.consume();
}
});
//drag detection for node dragging
node_root.setOnDragDetected( new EventHandler <MouseEvent> () {
@Override
public void handle(MouseEvent event) {
System.out.println("Drag detected");
//begin drag ops
relocateToPoint(new Point2D(event.getSceneX(), event.getSceneY()));
ClipboardContent content = new ClipboardContent();
content.putString("node_drag");
node_root.startDragAndDrop (TransferMode.ANY).setContent(content);
event.consume();
}
});
}
}
看来这是 JavaFX 中的真正错误。提交错误报告。目前计划在 JDK 9
中修复
此错误特定于 Linux 平台。
我测试了我的代码和你的代码,在 Windows 7 上一切正常,但在 Linux 上出现了错误。 (我还没有在 MacOs 上测试过)。
我用的是:OpenJdk 11.0.2
JDK 问题跟踪器中的问题:
https://bugs.openjdk.java.net/browse/JDK-8088458
还有一个与拖放和 GTK3 相关的错误:
我一直在尝试在 JavaFX 中实现节点拖动,我遇到了一个看起来应该相对容易解决的问题。我猜这与 window 调整大小后 JavaFX 场景图如何更新(或不更新)有关。
反正问题如下:
该应用程序以一个小的 window 开始,只有一个节点可以单击并在 window 周围拖动。这在两种情况下工作正常:
- 在调整大小之前,在 window 中单击并拖动节点。
- 调整大小后在window中单击并拖动节点。
但是第三次失败了:
- 在 window 调整大小(放大)之前和之后单击并拖动节点。
似乎拖动事件无法识别 window 边界的变化。换句话说,如果我单击并拖动节点,则放大 window。随后的点击和拖动尝试将被限制在 window 的原始范围内。
无论如何,下面是我编写的示例 JavaFX 应用程序来演示此问题。它复制了我上面描述的三个测试用例。
谢谢。
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.event.EventHandler;
public class Main extends Application {
private AnchorPane node_root;
private BorderPane mRoot;
@Override
public void start(Stage primaryStage) {
try {
node_root = new AnchorPane();
mRoot = new BorderPane();
Scene scene = new Scene(mRoot,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
addFileSystemNode ();
mRoot.setOnDragDone (new EventHandler <DragEvent>() {
@Override
public void handle(DragEvent event) {
System.out.println ("Drag done");
event.consume();
}
});
}
public static void main(String[] args) {
launch(args);
}
public final void addFileSystemNode () {
Label node_title = new Label();
node_title.setText("drag me!");
node_root.getChildren().add (node_title);
mRoot.getChildren().add (node_root);
buildNodeDragHandlers();
node_root.setLayoutX(100.0);
node_root.setLayoutY(100.0);
}
public void relocateToPoint (Point2D p) {
Point2D p2 = mRoot.sceneToLocal(p);
node_root.relocate (
(int) (p2.getX()),
(int) (p2.getY())
);
}
public void buildNodeDragHandlers() {
mRoot.setOnDragOver(new EventHandler <DragEvent>() {
//dragover to handle node dragging in the right pane view
@Override
public void handle(DragEvent event) {
System.out.println("parent node drag over" + " " + ((Pane) event.getSource()).getId());
event.acceptTransferModes(TransferMode.ANY);
relocateToPoint(new Point2D( event.getSceneX(), event.getSceneY()));
event.consume();
}
});
mRoot.setOnDragDropped(new EventHandler <DragEvent> () {
@Override
public void handle(DragEvent event) {
System.out.println("node drag dropped");
event.setDropCompleted(true);
event.consume();
}
});
//drag detection for node dragging
node_root.setOnDragDetected( new EventHandler <MouseEvent> () {
@Override
public void handle(MouseEvent event) {
System.out.println("Drag detected");
//begin drag ops
relocateToPoint(new Point2D(event.getSceneX(), event.getSceneY()));
ClipboardContent content = new ClipboardContent();
content.putString("node_drag");
node_root.startDragAndDrop (TransferMode.ANY).setContent(content);
event.consume();
}
});
}
}
看来这是 JavaFX 中的真正错误。提交错误报告。目前计划在 JDK 9
中修复此错误特定于 Linux 平台。 我测试了我的代码和你的代码,在 Windows 7 上一切正常,但在 Linux 上出现了错误。 (我还没有在 MacOs 上测试过)。
我用的是:OpenJdk 11.0.2
JDK 问题跟踪器中的问题:
https://bugs.openjdk.java.net/browse/JDK-8088458
还有一个与拖放和 GTK3 相关的错误: