JavaFX Container Draggable

时间:2014-10-20 12:47:30

标签: java javafx mouseevent draggable

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

这是我的代码:

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 个答案:

答案 0 :(得分: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);
    }
}