【问题标题】:Proper way to move a JavaFx8 node around移动 JavaFx8 节点的正确方法
【发布时间】:2015-01-20 16:50:07
【问题描述】:

我正在开发一个需要在窗格上移动节点的应用程序。

我最近刚开始学习 javaFx 8,所以我对工作流程几乎没有了解,但是当我设法让可拖动的节点代码正常工作时,它使用 node.setTranslateX() 和 .setTranslateY()。

这一切都很好,直到我尝试让节点捕捉到一个网格,该网格将场景区域分为 10 个高度和宽度细分。

每当我尝试使用模数来进行某种捕捉时,我都会坚持我称之为平移转换的事实。我想自己直接设置节点的坐标。我试过 node.relocate(x,y) 无济于事。至于 node.setX() 或 node.setY()。这些似乎没有多大作用。

所以基本上,我有两个问题:

  • 有没有办法直接设置节点的坐标?如果是,如何?
  • 在用鼠标拖动节点时将节点捕捉到网格的正确方法是什么?

我当前的代码使用这些方法来拖动节点:

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);
    });
}

提前感谢您的帮助,

【问题讨论】:

  • 你把这个放在什么样的容器 (Pane) 里?

标签: java draggable javafx-8


【解决方案1】:

在大多数Pane 子类中,如果Nodemanaged,则节点的父窗格将管理其layoutXlayoutY 属性。所以为这些节点设置layoutXlayoutY对节点的位置没有明显的影响。

转换(包括translateXtranslateY 定义的转换)在布局计算后应用于节点(无论该节点是否由其父节点管理)。

所以管理拖动的一种方法就是操纵translateXtranslateY 属性。另一种方法是操纵layoutXlayoutY 属性(通过直接设置它们或通过调用relocate),并确保节点不受其父节点管理。我不建议混合使用这两种技术,因为您的代码将更难遵循。

您可以将节点上的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);
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 2019-03-14
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多