我目前在窗格上有一些堆栈窗格,当用鼠标拖动它们时,它们会在窗格中移动。我通过获取鼠标的坐标来实现 以及按下堆栈窗格时堆栈窗格的平移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。现在一切正常!
答案 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。
根据以上信息,如果我们现在查看您的代码,则您正在更新转换值并错误地设置了布局值。相反,您实际要做的是:
下面是我所描述内容的快速演示。
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,并查看行为差异。