java 移动 JavaFx8 节点的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27080039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proper way to move a JavaFx8 node around
提问by Skwiggs
I am working on an app which needs to move nodes around on a pane.
我正在开发一个需要在窗格上移动节点的应用程序。
I've just recently started learning javaFx 8 so I have bare understanding of the workflow, but while I managed to get a working draggable node code working, it uses node.setTranslateX() and .setTranslateY().
我最近才开始学习 javaFx 8,所以我对工作流程一无所知,但是虽然我设法让一个工作的可拖动节点代码工作,但它使用 node.setTranslateX() 和 .setTranslateY()。
This is all fine, until I tried to make the node snap to a grid that divides the scene area in both 10 height and width subdivisions.
这一切都很好,直到我试图使节点对齐到一个网格,该网格将场景区域划分为 10 个高度和宽度细分。
Whenever I try to use modulos to get some sort of snapping going on, I'm stuck with the fact that I'm calling Translation transformation. I'd like to directly set the coordinates of the node myself. I've tried node.relocate(x,y) to no avail. As for node.setX() or node.setY(). These do no seem to do much.
每当我尝试使用模数来进行某种捕捉时,我都会坚持我正在调用翻译转换这一事实。我想自己直接设置节点的坐标。我试过 node.relocate(x,y) 无济于事。至于 node.setX() 或 node.setY()。这些似乎没有多大作用。
So basically, I have two questions:
所以基本上,我有两个问题:
- Is there a way to directly set the coordinates of a node ? If yes, how ?
- What is the correct way to snap a node to a grid while dragging it with the mouse ?
- 有没有办法直接设置节点的坐标?如果是,如何?
- 在用鼠标拖动节点时将节点对齐到网格的正确方法是什么?
My current code uses these methods to drag the node around:
我当前的代码使用这些方法来拖动节点:
public class Boat extends ImageView {
private int size ;
private String name ;
private Double dragDeltaX, dragDeltaY;
//Constructor etc here//
this.setOnMousePressed(event -> {
this.setCursor(Cursor.CLOSED_HAND);
dragDeltaX = this.getLayoutX() + event.getX();
dragDeltaY = this.getLayoutY() + event.getY();
});
this.setOnMouseReleased(event -> {
this.setCursor(Cursor.OPEN_HAND);
this.relocate(event.getSceneX(), event.getSceneY());
});
this.setOnMouseDragged(event -> {
this.setTranslateX(event.getSceneX() - dragDeltaX);
this.setTranslateY(event.getSceneY() - dragDeltaY);
});
this.setOnMouseEntered(event -> {
this.setCursor(Cursor.OPEN_HAND);
});
}
Thanks in advance for the help,
在此先感谢您的帮助,
回答by James_D
In most Pane
subclasses, if a Node
is managed
, then the parent pane of the node will manage its layoutX
and layoutY
properties. So setting layoutX
and layoutY
for these nodes will have no visible effect on the position of the node.
在大多数Pane
子类中,如果 aNode
是managed
,则节点的父窗格将管理其layoutX
和layoutY
属性。因此layoutX
,layoutY
为这些节点设置和将不会对节点的位置产生明显影响。
Transformations (including the translation defined by translateX
and translateY
) are applied to nodes after the layout calculations (whether the node is managed by its parent or not).
转换(包括由translateX
和定义的转换translateY
)在布局计算后应用于节点(无论节点是否由其父节点管理)。
So one way to manage dragging is just to manipulate the translateX
and translateY
properties. Another way is to manipulate the layoutX
and layoutY
properties (by setting them directly or by calling relocate
), and make sure the node is not managed by its parent. I would not recommend mixing the two techniques, as your code will be harder to follow.
因此,管理拖动的一种方法是操作translateX
和translateY
属性。另一种方法是操作layoutX
和layoutY
属性(通过直接设置它们或通过调用relocate
),并确保节点不受其父节点管理。我不建议混合使用这两种技术,因为您的代码将更难遵循。
You can make the node unmanaged setManaged(false)
on the node, or by putting it in a Pane
instead of one of the subclasses (Pane
does not manage layout of its child nodes).
您可以使节点在节点上不受管理setManaged(false)
,或者将其放在一个Pane
而不是子类中(Pane
不管理其子节点的布局)。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ImageViewDragExample extends Application {
@Override
public void start(Stage primaryStage) {
Image image = createImage();
DraggableImageView imageView = new DraggableImageView(image);
// if the node is placed in a parent that manages its child nodes,
// you must call setManaged(false);
// imageView.setManaged(false);
// StackPane root = new StackPane(imageView);
// or use a plain `Pane`, which does not manage its child nodes:
Pane root = new Pane(imageView);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private Image createImage() {
WritableImage image = new WritableImage(50, 50);
for (int y = 0 ; y < 50; y++) {
for (int x = 0 ; x < 50 ; x++) {
Color c ;
if ((x > 20 && x < 30) || (y > 20 && y < 30)) {
c = Color.AZURE ;
} else {
c = Color.CORNFLOWERBLUE ;
}
image.getPixelWriter().setColor(x, y, c);
}
}
return image ;
}
public static class DraggableImageView extends ImageView {
private double mouseX ;
private double mouseY ;
public DraggableImageView(Image image) {
super(image);
setOnMousePressed(event -> {
mouseX = event.getSceneX() ;
mouseY = event.getSceneY() ;
});
setOnMouseDragged(event -> {
double deltaX = event.getSceneX() - mouseX ;
double deltaY = event.getSceneY() - mouseY ;
relocate(getLayoutX() + deltaX, getLayoutY() + deltaY);
mouseX = event.getSceneX() ;
mouseY = event.getSceneY() ;
});
}
}
public static void main(String[] args) {
launch(args);
}
}