JavaFX容器可拖动

JavaFX容器可拖动,java,javafx,mouseevent,draggable,Java,Javafx,Mouseevent,Draggable,我在JavaFX中有一个可拖动的容器。此容器在弹出窗口中实现。我可以拖动容器,但是如果我拖动它,鼠标事件没有恒定的坐标。鼠标位置在两个固定位置之间快速切换 这是我的密码: container.setOnMouseDragged(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent me) { // TODO Au

我在JavaFX中有一个可拖动的容器。此容器在弹出窗口中实现。我可以拖动容器,但是如果我拖动它,鼠标事件没有恒定的坐标。鼠标位置在两个固定位置之间快速切换

这是我的密码:

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());
                }
            }
        });
container.setonMouseDrawed(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent me){
//TODO自动生成的方法存根
如果(dragAct==true){
//将弹出窗口的位置设置为鼠标的位置
setX(me.getX());
setY(me.getY());
}
}
});
容器是一个VBox。Main类是PopUp类的扩展版本

JavaFX Container Draggable
您调用的setX和setY方法在屏幕坐标中设置弹出窗口的位置。对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);
    }
}
导入javafx.application.application;
导入javafx.beans.property.ObjectProperty;
导入javafx.beans.property.SimpleObject属性;
导入javafx.geometry.Point2D;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.layout.StackPane;
导入javafx.stage.Popup;
导入javafx.stage.stage;
公共类DraggingPopup扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
按钮按钮=新按钮(“显示弹出窗口”);
按钮。设置操作(事件->ShowDragablePopup(primaryStage));
StackPane根=新建StackPane(按钮);
场景=新场景(根,250,75);
初级阶段。场景(场景);
primaryStage.show();
}
私有void showDraggablePopup(后台所有者){
Popup Popup=新的Popup();
按钮关闭按钮=新按钮(“关闭”);
closeButton.setOnAction(事件->弹出窗口.hide());
StackPane容器=新的StackPane(关闭按钮);
container.setStyle(“-fx背景色:钢蓝;”);
容器。设置最小宽度(300);
容器。设置最小高度(125);
//拖动实现:
ObjectProperty mouseLocation=新的SimpleObjectProperty();
container.setOnMousePressed(事件->
set(新的Point2D(event.getScreenX(),event.getScreenY());
container.setOnMouseDrawed(事件->{
if(mouseLocation.get()!=null){
double x=event.getScreenX();
double deltaX=x-mouseLocation.get().getX();
double y=event.getScreenY();
double deltaY=y-mouseLocation.get().getY();
//如果有两个或两个以上的电脑屏幕,这有助于我避免卡在一个屏幕上
if(Math.abs(popup.getX()-x)>popup.getWidth()){
popup.setX(x);
setY(y);
}否则{
popup.setX(popup.getX()+deltaX);
popup.setY(popup.getY()+deltaY);
}
mouseLocation.set(新点2d(x,y));
}
});
container.setOnMouseReleased(事件->鼠标定位.set(null));
popup.getScene().setRoot(容器);
弹出显示(所有者);
}
公共静态void main(字符串[]args){
发射(args);
}
}

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