javafx,拖动优化 - 各种想法

标签 java javafx

我有一个包含很多可拖动节点的应用程序,它可能会变得有点慢。特别是在:

  • 拖动包含其他节点的节点或
  • 将 Node 拖到另一个 IF 中会导致扩大父级的边界 [几乎就像它正在缓存一些与范围相关的数据,内部 double 值很常见,并且如果范围发生变化则需要进行额外处理](编辑:这有现在被解释为父级的布局传递)

问:对整数执行某些操作(我可以控制类型的少数操作)(首先转换为整数)然后重新分配给 double 值有什么好处吗? (编辑:现在已经回答了)

问题 1:我还能如何加快速度?

==========更新: 感谢到目前为止的建议,我确定我的主要问题是在区域根内平移区域容器,因为它会触发容器区域中的布局传递,这反过来(我认为)乒乓球在所有( ca. 40) 子节点(它们本身很复杂 - 它们包含文本字段、按钮等)。

到目前为止,我找到的最快的解决方案是在一个组中平移一个组(已经快了很多),其中组被额外修改(子类,覆盖计算...方法)以确保父/根不需要在拖动过程中调整大小(遗憾的是,不是很明显)。

class FastGroup extends Group {
    //'stop asking about size' functionality

    double widthCache;
    double heightCache;

    protected double computePrefWidth(double height) {
        return widthCache != 0 ? widthCache : super.computePrefWidth(height);
    }

    protected double computePrefHeight(double width) {
            return heightCache != 0 ? heightCache : super.computePrefHeight(width);

    }

    public void initDragging(){
    //if a child of this Group goes into drag
    //add max margins to Group's size 
        double newW = getBoundsInLocal().getWidth() + TestFXApp03.scene.getWidth()*2;
        double newH = getBoundsInLocal().getHeight() + TestFXApp03.scene.getHeight()*2;
    //cache size
        widthCache = newW;
        heightCache = newH;
    }

    public void endDragging(){
        widthCache = 0;
        heightCache = 0;
    }
}

然而,Group 自身也存在问题。

问题 3:为什么我不能使用 Pane 实现相同的效果(尝试将其作为第三个选项)?根据文档,一个 Pane :

'does not perform layout beyond resizing resizable children to their preferred size'

...当一个组:

'will "auto-size" its managed resizable children to their preferred sizes during the layout pass'

'is not directly resizable'

...这对我来说听起来很相似,但是用作根的 Pane 导致所包含的组的平移非常缓慢。

最佳答案

好的...我花了一些时间检查鼠标拖动多个对象的性能...

我是在 Mac Pro(4 核,8GB RAM)上完成的。

  1. 在 setOnMouseDragged() 处理程序中使用 setTranslateX() 和 setTranslateY() 以 17 毫秒 (60Hz) 的间隔调用鼠标拖动。
  2. 如果我向拖动组添加小圆圈,拖动会保持其速度,最多拖动 25.000 个圆圈。
  3. 在 100.000 圈时,拖动间隔约为 50 毫秒(并在拖动过程中显示一些停顿)
  4. 在 1.000.000 圈时,拖动间隔约为 500 毫秒

如果我使用 snapshot() 函数将拖动实现为图像拖动,则 1.000.000 圈的快照需要 600 毫秒。然后拖动顺畅快速。

这里是在拖动过程中使用和不使用图像的完整代码:

public class DragMany extends Application {
    Point2D lastXY = null;
    Scene myScene;
    long lastDrag;
    ImageView dragImage; 


    void fill(Group box) {
        Color colors[] = new Color[]{Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.PINK, Color.MAGENTA };
        for (int i = 0; i < 100000; i++) {
            Circle c = new Circle(2);
            box.getChildren().add(c);
            c.setFill(colors[(i/17) % colors.length]);
            c.setLayoutX(i % 30 * 3);
            c.setLayoutY((i/20) % 30*3);
        }
        box.setLayoutX(40);
        box.setLayoutY(40);

    }
    void drag1(Pane pane, Group box) {
        box.setOnMousePressed(event -> {
            lastXY = new Point2D(event.getSceneX(), event.getSceneY());
            lastDrag = System.currentTimeMillis();
        });
        box.setOnMouseDragged(event -> {
            event.setDragDetect(false);
            Node on = box;
            double dx = event.getSceneX() - lastXY.getX();
            double dy = event.getSceneY() - lastXY.getY();
            on.setLayoutX(on.getLayoutX()+dx);
            on.setLayoutY(on.getLayoutY()+dy);
            lastXY = new Point2D(event.getSceneX(), event.getSceneY());
            event.consume();
        });

        box.setOnMouseReleased(d ->  lastXY = null);
    }

    void drag3(Pane pane, Group box) {
        box.setOnMousePressed(event -> {
            long now = System.currentTimeMillis();

            lastXY = new Point2D(event.getSceneX(), event.getSceneY());
            SnapshotParameters params = new SnapshotParameters();
            params.setFill(Color.TRANSPARENT);
            WritableImage image = box.snapshot(params, null);
            dragImage = new ImageView(image);
            dragImage.setLayoutX(box.getLayoutX());
            dragImage.setLayoutY(box.getLayoutY());
            dragImage.setTranslateX(box.getTranslateX());
            dragImage.setTranslateY(box.getTranslateY());
            pane.getChildren().add(dragImage);
            dragImage.setOpacity(0.5);
            box.setVisible(false);
            System.out.println("Snap "+(System.currentTimeMillis()-now)+"ms");

            pane.setOnMouseDragged(e -> {
                if (dragImage == null) return;
                Node on = dragImage;
                double dx = e.getSceneX() - lastXY.getX();
                double dy = e.getSceneY() - lastXY.getY();
                on.setTranslateX(on.getTranslateX()+dx);
                on.setTranslateY(on.getTranslateY()+dy);
                lastXY = new Point2D(e.getSceneX(), e.getSceneY());
                e.consume();
            });
            pane.setOnMouseReleased(e -> {
                if (dragImage != null) {
                    box.setTranslateX(dragImage.getTranslateX());
                    box.setTranslateY(dragImage.getTranslateY());
                    pane.getChildren().remove(dragImage);
                    box.setVisible(true);
                    dragImage = null;
                }
                lastXY = null;
                e.consume();
            });

            lastDrag = System.currentTimeMillis();
            event.consume();
        });
    }

    public void start(Stage primaryStage) {
        Pane mainPane = new Pane(); 
        myScene = new Scene(mainPane, 500, 500);
        primaryStage.setScene(myScene);
        primaryStage.show();

        Group all = new Group();
        fill(all);
        mainPane.getChildren().add(all);
        drag3(mainPane, all);
    }

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

关于javafx,拖动优化 - 各种想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27210819/

相关文章:

java - 通过查看枚举将剩余颜色添加到数组列表中

java - 如何使用 PixelReader 和 JavaFX 提取子图像?

java - 使用打印格式均匀间隔一位或多位数字的整数显示

java - 如何在没有可显示组件的情况下使用 Java 获得 VLC 媒体播放器?

android - Netbeans 8.1,Gluon 项目 Android 错误

java - 如何在 Java FX 上可视化矩阵

Java - 文本字段的模式

java - 如何检查执行器何时完成运行特定的 Runnable

java - 从 JavaFX TableView 中一次删除多行的问题

java - 如何在不改变布局和布局的情况下缩放xml中的节点