JavaFX 通过拖放在 ScrollPane 中移动对象
JavaFX moving Objects within ScrollPane by drag and drop
我在 ScrollPane 中有一个非常大的 StackPane(3000x2000)。这个想法是像一个大 "drawing board" 一样使用它,用户可以在其中创建节点并将它们拖来拖去,以创建思维导图等。问题是拖放:如果 scrollPane 在它的 "start position" 中,它工作正常,因此 Hvalue 和 Vvalue 都是 0。但是一旦你滚动了一下,DragEvent.getX() 和 . getY() return 相对于窗格的可见部分,而不是其整个大小。这意味着您无法正确拖放某些东西。我创建了一个测试 class 来说明问题,没有任何过时的代码:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class DragTestClass extends Application{
public static void problem(Circle circle, ScrollPane scrollPane, StackPane pane, DataFormat dataFormat){
circle.setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Dragboard db = circle.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.put(dataFormat,0); // normally, ID of node
db.setContent(content);
event.consume();
}
});
scrollPane.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if(db.hasContent(dataFormat) && db.getContent(dataFormat) instanceof Integer){
int index = (Integer) db.getContent(dataFormat);
Circle node = (Circle) pane.getChildren().get(index);
node.setManaged(false);
// this is the problematic part
node.setTranslateX(event.getX() - node.getCenterX());
node.setTranslateY(event.getY() - node.getCenterY());
event.setDropCompleted(true);
event.consume();
}
}
});
scrollPane.setOnDragOver(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
});
}
@Override
public void start(Stage primaryStage) throws Exception {
ScrollPane scrollPane = new ScrollPane();
StackPane pane = new StackPane();
DataFormat dataFormat = new DataFormat("DragDropFormat");
int width = 1000;
int height = 1000;
pane.setMinHeight(height);
pane.setMaxHeight(height);
pane.setMinWidth(width);
pane.setMaxWidth(width);
Circle circle = new Circle(50,50,20); // normally a StackPane
circle.setManaged(false);
pane.getChildren().add(circle);
pane.setAlignment(Pos.TOP_LEFT);
scrollPane.setContent(pane);
problem(circle, scrollPane, pane, dataFormat);
Scene scene = new Scene(scrollPane, 400, 400);
primaryStage.setTitle("Problem");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我的想法是在节点的平移中添加一些东西,比如 scrollPane.getHvalue() * width,但这似乎不起作用。也许我只是用谷歌搜索了错误的关键字,但我没有找到任何有用的东西,所以如果这个问题在其他地方得到了回答,我很抱歉。预先感谢您的帮助!
我想通了!在 StackPane 上设置 EventHandler(ScrollPane 的内容,而不是 ScrollPane 本身)达到了目的。显然,event.getX() returns 的坐标是相对于具有 EventHandler 的节点的。在这个例子中:
pane.setOnDragDropped...
我在 ScrollPane 中有一个非常大的 StackPane(3000x2000)。这个想法是像一个大 "drawing board" 一样使用它,用户可以在其中创建节点并将它们拖来拖去,以创建思维导图等。问题是拖放:如果 scrollPane 在它的 "start position" 中,它工作正常,因此 Hvalue 和 Vvalue 都是 0。但是一旦你滚动了一下,DragEvent.getX() 和 . getY() return 相对于窗格的可见部分,而不是其整个大小。这意味着您无法正确拖放某些东西。我创建了一个测试 class 来说明问题,没有任何过时的代码:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class DragTestClass extends Application{
public static void problem(Circle circle, ScrollPane scrollPane, StackPane pane, DataFormat dataFormat){
circle.setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Dragboard db = circle.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.put(dataFormat,0); // normally, ID of node
db.setContent(content);
event.consume();
}
});
scrollPane.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if(db.hasContent(dataFormat) && db.getContent(dataFormat) instanceof Integer){
int index = (Integer) db.getContent(dataFormat);
Circle node = (Circle) pane.getChildren().get(index);
node.setManaged(false);
// this is the problematic part
node.setTranslateX(event.getX() - node.getCenterX());
node.setTranslateY(event.getY() - node.getCenterY());
event.setDropCompleted(true);
event.consume();
}
}
});
scrollPane.setOnDragOver(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.ANY);
event.consume();
}
});
}
@Override
public void start(Stage primaryStage) throws Exception {
ScrollPane scrollPane = new ScrollPane();
StackPane pane = new StackPane();
DataFormat dataFormat = new DataFormat("DragDropFormat");
int width = 1000;
int height = 1000;
pane.setMinHeight(height);
pane.setMaxHeight(height);
pane.setMinWidth(width);
pane.setMaxWidth(width);
Circle circle = new Circle(50,50,20); // normally a StackPane
circle.setManaged(false);
pane.getChildren().add(circle);
pane.setAlignment(Pos.TOP_LEFT);
scrollPane.setContent(pane);
problem(circle, scrollPane, pane, dataFormat);
Scene scene = new Scene(scrollPane, 400, 400);
primaryStage.setTitle("Problem");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我的想法是在节点的平移中添加一些东西,比如 scrollPane.getHvalue() * width,但这似乎不起作用。也许我只是用谷歌搜索了错误的关键字,但我没有找到任何有用的东西,所以如果这个问题在其他地方得到了回答,我很抱歉。预先感谢您的帮助!
我想通了!在 StackPane 上设置 EventHandler(ScrollPane 的内容,而不是 ScrollPane 本身)达到了目的。显然,event.getX() returns 的坐标是相对于具有 EventHandler 的节点的。在这个例子中:
pane.setOnDragDropped...