JavaFX 容器可拖动

Posted

技术标签:

【中文标题】JavaFX 容器可拖动【英文标题】:JavaFX Container Draggable 【发布时间】:2014-12-15 11:03:31 【问题描述】:

我在 JavaFX 中有一个可拖动的容器。此 Container 在 PopUp 中实现。我可以拖动容器,但是如果我拖动它,鼠标事件没有一个恒定的坐标。在 2 个固定位置之间切换鼠标位置非常快。

这是我的代码:

container.setOnMouseDragged(new EventHandler<MouseEvent>() 

            @Override
            public void handle(MouseEvent me) 
                // TODO Auto-generated method stub

                if(dragAct==true)
                    //Set the Position of the PopUp to the Position of the Mouse
                    setX(me.getX());
                    setY(me.getY());
                
            
        );

容器是一个VBox。 Main-Class 是 PopUp-Class 的扩展版本。

【问题讨论】:

【参考方案1】:
JavaFX Container Draggable

您调用的 setX 和 setY 方法设置 Popup 在屏幕坐标中的位置。对 me.getX() 和 me.getY() 的调用为您提供了鼠标相对于容器的坐标。当您移动弹出窗口时,容器也会移动,因此鼠标的位置相对于容器发生了变化。因此,从一个拖动事件到下一个拖动事件,您的计算将不一致。

解决方法是计算相对于固定对象的位置。由于您正在移动弹出窗口,这是一个窗口,因此固定坐标系是屏幕坐标系。 MouseEvent 具有 getScreenX 和 getScreenY 方法,您可以使用这些方法轻松获取它们。

我喜欢通过保存最后一个鼠标位置然后计算拖动时移动的距离来实现拖动。还有其他(可能不太冗长)方法可以做到这一点,但对我来说这是最清楚的:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;

public class DraggingPopup extends Application 

    @Override
    public void start(Stage primaryStage) 
        Button button = new Button("Show popup");
        button.setOnAction(event -> showDraggablePopup(primaryStage));
        StackPane root = new StackPane(button);
        Scene scene = new Scene(root, 250, 75);
        primaryStage.setScene(scene);
        primaryStage.show();
    

    private void showDraggablePopup(Stage owner) 
        Popup popup = new Popup();
        Button closeButton = new Button("Close");
        closeButton.setOnAction(event -> popup.hide());
        StackPane container = new StackPane(closeButton);
        container.setStyle("-fx-background-color: steelblue;");
        container.setMinWidth(300);
        container.setMinHeight(125);

        // Dragging implementation:

        ObjectProperty<Point2D> mouseLocation = new SimpleObjectProperty<>();

        container.setOnMousePressed(event -> 
            mouseLocation.set(new Point2D(event.getScreenX(), event.getScreenY())));

        container.setOnMouseDragged(event -> 
            if (mouseLocation.get() != null) 
                double x = event.getScreenX();
                double deltaX = x - mouseLocation.get().getX() ;
                double y = event.getScreenY();
                double deltaY = y - mouseLocation.get().getY() ;
                //in case of 2 or more computer screens this help me to avoid get stuck on 1 screen
                if(Math.abs(popup.getX()-x)>popup.getWidth())
                   popup.setX(x);
                   popup.setY(y);
                else 
                popup.setX(popup.getX() + deltaX);
                popup.setY(popup.getY() + deltaY);
                
                mouseLocation.set(new Point2D(x, y));
            
        );

        container.setOnMouseReleased(event -> mouseLocation.set(null));

        popup.getScene().setRoot(container);
        popup.show(owner);
    

    public static void main(String[] args) 
        launch(args);
    

【讨论】:

它工作得很好,我有另一个关于弹出窗口的问题。目前PopUp可能会离开主舞台...是否可以在主舞台绑定PopUp。应该不允许离开主舞台的窗口...有没有解决办法,我试过很多,但我不知道我该如何解决这个问题 在移动前检查主舞台的位置、宽度和高度,以及弹出窗口的宽度和高度。 感谢您的回答,没有集成自动功能吗?我必须用数学来解决问题? 不会比调用Math.min(...)Math.max(...)复杂多少

以上是关于JavaFX 容器可拖动的主要内容,如果未能解决你的问题,请参考以下文章

jquery UI可拖动:在容器内水平拖动溢出:滚动?

如何使嵌套元素在可拖动容器中不可拖动?

隐藏在容器外的可拖动元素

可拖动元素的遏制

拖动具有滚动的容器时,可拖动项目不可见

拖动功能无法正常工作! JavaFX VBox 拖动