翻译节点后,布局x和y保持不变

时间:2018-11-11 21:50:37

标签: javafx

我目前在窗格上有一些堆栈窗格,当用鼠标拖动它们时,它们会在窗格中移动。我通过获取鼠标的坐标来实现  以及按下堆栈窗格时堆栈窗格的平移x和y。然后,当我开始拖动堆栈窗格时,我在按下堆栈窗格时将堆栈窗格的平移x和y设置为鼠标坐标+新鼠标坐标与旧鼠标坐标的差。

我的问题是,在拖动StackPane之后,布局x和y保持不变,我想像在其他地方那样使用它来更新它。

当您按下StackPane时,我的事件处理程序:

EventHandler<MouseEvent> circleOnMousePressedEventHandler = 
            new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {

                currentStackPane  = ((StackPane)(t.getSource()));
                orgSceneX = t.getSceneX();
                orgSceneY = t.getSceneY();
                layoutX =  currentStackPane.getLayoutX();
                layoutY =  currentStackPane.getLayoutY();

            }
        };

我拖动StackPane时的事件处理程序:

EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = 
            new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {


                double offsetX = t.getSceneX() - orgSceneX;
                double offsetY = t.getSceneY() - orgSceneY;
                currentStackPane.setTranslateX(offsetX);
                currentStackPane.setTranslateY(offsetY);
             }
        };

在拖动完成后,我尝试制作一个事件处理程序:

EventHandler<MouseEvent> circleOnMouseReleasedEventHandler = 
            new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {

                currentStackPane.setLayoutX(layoutX + ((StackPane)(t.getSource())).getTranslateX());
                currentStackPane.setLayoutY(layoutY + ((StackPane)(t.getSource())).getTranslateY());
                currentStackPane.setTranslateX(0);
                currentStackPane.setTranslateY(0);
        }
};

但这似乎不起作用。任何帮助将不胜感激,谢谢!

编辑:

我更改了事件处理程序。我第一次拖动堆栈窗格时似乎似乎正确地更新了布局x和y,但是当我第一次拖动堆栈窗格然后释放鼠标时,堆栈窗格移动到一个不同的位置,然后每次将其完全弄乱后进行拖动。不知道为什么,感谢您的帮助!

EDIT2:我意识到我在鼠标释放事件中将translation x设置为0,但没有将y设置为0。现在一切正常!

1 个答案:

答案 0 :(得分:1)

要了解该问题,我首先建议您查看一下Node的layoutX / layoutY属性的文档。

  

公共最终DoubleProperty layoutXProperty

     

定义添加到此的平移的x坐标   以布局为目的的节点变换。该值应为   计算为调整节点位置所需的偏移量   从其当前layoutBounds minX位置(可能不为0)到   所需的位置。

     

例如,如果textnode应该位于finalX

 textnode.setLayoutX(finalX - textnode.getLayoutBounds().getMinX());  
     

未能减去layoutBounds minX可能会导致放错位置   节点。 relocate(x,y)方法将自动执行正确的操作   计算,通常应在设置layoutX时使用   直接。

     

节点的最终翻译将计算为layoutX + translateX,   其中layoutX建立节点的稳定位置,然后translationX   (可选)对该位置进行动态调整。

     

如果节点是托管节点,并且其父节点为Region,则布局   区域将根据自己的布局策略设置layoutX。如果   节点不受组管理或作为组的父项,则应用程序可能会设置   layoutX直接定位它。

简而言之,对于场景中渲染的每个节点,其位置实际上是其相对于其父节点的layoutX / Y和translateX / Y值的总和。最初根据其父级布局策略更新layoutX / Y。因此,没有必要更新/依靠节点的layoutX / Y值, IF 由其父节点(例如.StackPane,HBox,VBox等)管理其位置。 >

Pane不会管理/确定其子级布局。因此,其子级的默认layoutX / Y值始终为0。

根据以上信息,如果我们现在查看您的代码,则您正在更新转换值并错误地设置了布局值。相反,您实际要做的是:

  1. 获取layoutX / Y的初始值。
  2. 拖动时更新translateX / Y。
  3. 在释放鼠标后重新计算layoutX / Y值并重置 translationX / Y值。

下面是我所描述内容的快速演示。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class PaneLayoutDemo extends Application {
    double sceneX, sceneY, layoutX, layoutY;

    @Override
    public void start(Stage stage) throws Exception {
        Pane root = new Pane();
        Scene sc = new Scene(root, 600, 600);
        stage.setScene(sc);
        stage.show();
        root.getChildren().addAll(getBox("green"), getBox("red"), getBox("yellow"));
    }

    private StackPane getBox(String color) {
        StackPane box = new StackPane();
        box.getChildren().add(new Label("Drag me !!"));
        box.setStyle("-fx-background-color:" + color + ";-fx-border-width:2px;-fx-border-color:black;");
        box.setPrefSize(150, 150);
        box.setMaxSize(150, 150);
        box.setMinSize(150, 150);
        box.setOnMousePressed(e -> {
            sceneX = e.getSceneX();
            sceneY = e.getSceneY();
            layoutX = box.getLayoutX();
            layoutY = box.getLayoutY();
            System.out.println(color.toUpperCase() + " Box onStart :: layoutX ::" + layoutX + ", layoutY::" + layoutY);
        });
        box.setOnMouseDragged(e -> {
            double offsetX = e.getSceneX() - sceneX;
            double offsetY = e.getSceneY() - sceneY;
            box.setTranslateX(offsetX);
            box.setTranslateY(offsetY);
        });
        box.setOnMouseReleased(e -> {
            // Updating the new layout positions
            box.setLayoutX(layoutX + box.getTranslateX());
            box.setLayoutY(layoutY + box.getTranslateY());

            // Resetting the translate positions
            box.setTranslateX(0);
            box.setTranslateY(0);
        });
        return box;
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

一旦您熟悉了演示,请尝试将根目录从Pane更改为StackPane,并查看行为差异。