当前位置: 首页 > 知识库问答 >
问题:

通过拖动javafx 2来移动节点的正确方法?

麹学文
2023-03-14

我正在将一个包含大量自定义绘制的Swing/Graphics2D应用程序转换为JavaFX2应用程序。虽然我非常喜欢这个新的API,但当我在鼠标光标下方绘制椭圆时,无论鼠标移动到哪里,我似乎都会遇到性能问题。当我以稳定的方式移动鼠标时,我注意到椭圆总是在鼠标轨迹的后面几厘米处绘制,只有当我停止移动光标时,椭圆才会出现。这是一个只有少数节点的场景图。在我的Swing应用程序中,我没有这个问题。

我想知道这是否是在鼠标器所在位置绘制形状的正确方法?

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.EllipseBuilder;
import javafx.stage.Stage;

public class TestApp extends Application {
public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
    Pane p = new Pane();

    final Ellipse ellipse = EllipseBuilder.create().radiusX(10).radiusY(10).fill(Color.RED).build();
    p.getChildren().add(ellipse);

    p.setOnMouseMoved(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent event) {
            ellipse.setCenterX(event.getX());
            ellipse.setCenterY(event.getY());
        }
    });

    Scene scene = SceneBuilder.create().root(p).width(1024d).height(768d).build();
    primaryStage.setScene(scene);

    primaryStage.show();
}
}

小更新:我升级到JavaFX2.2和Java7u6(在64位Windows 7上),但似乎没有什么不同。

共有3个答案

诸葛利
2023-03-14

对我来说,这看起来不像绘画表现的问题,而是如何生成鼠标事件序列的问题。当鼠标快速移动时,事件不会实时生成,有些会被跳过。对于大多数应用程序,这将是足够的方式。鼠标指针实时移动,没有任何时间延迟。

如果你不想要这种效果,你将不得不直接听鼠标指针,或者想办法以更高的密度获取事件。我不知道我自己是怎么做到的。

蒋高扬
2023-03-14

您描述的滞后(鼠标和拖动的形状之间)是一个已知的JavaFX错误:

https://bugs.openjdk.java.net/browse/JDK-8087922

您可以通过使用未记录的JVM标志来解决它(至少在Windows上):

-Djavafx.animation.fullspeed=true

这个标志通常用于内部性能测试,这就是为什么它没有文档记录,但我们已经使用它几个月了,到目前为止还没有任何问题。

编辑:

还有另一种类似的方法来解决这个bug,它可能会在CPU使用上更容易一些。只需关闭Prism的垂直同步:

-Dprism.vsync=false

在我们的应用程序中,这两种解决方法都可以解决滞后问题;没有必要两者都做。

乌和畅
2023-03-14

这是我用来允许在窗格中拖动标签的一些代码。我没有注意到它在鼠标轨迹后面有任何明显的滞后。

// allow the label to be dragged around.
final Delta dragDelta = new Delta();
label.setOnMousePressed(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    // record a delta distance for the drag and drop operation.
    dragDelta.x = label.getLayoutX() - mouseEvent.getSceneX();
    dragDelta.y = label.getLayoutY() - mouseEvent.getSceneY();
    label.setCursor(Cursor.MOVE);
  }
});
label.setOnMouseReleased(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    label.setCursor(Cursor.HAND);
  }
});
label.setOnMouseDragged(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    label.setLayoutX(mouseEvent.getSceneX() + dragDelta.x);
    label.setLayoutY(mouseEvent.getSceneY() + dragDelta.y);
  }
});
label.setOnMouseEntered(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    label.setCursor(Cursor.HAND);
  }
});

. . .

// records relative x and y co-ordinates.
class Delta { double x, y; }

下面是一个使用上述代码的完整小示例应用程序

更新上面的例子,当被拖动的对象很小时,仍然会将被拖动的对象滞后在光标后面。

另一种方法是使用由叠加在被拖动节点的图像表示上的鼠标指针组成的ImageCursor,然后在拖动开始和完成时隐藏和显示实际节点。这意味着节点拖动渲染不会滞后于光标(因为节点的图像表示现在是光标)。然而,这种方法确实有缺点=

 类似资料:
  • 问题内容: 我正在将具有大量自定义绘画的Swing / Graphics2D应用程序转换为JavaFX2应用程序。尽管我绝对喜欢新的API,但是在绘制椭圆时我似乎遇到了性能问题,无论鼠标移动到哪里,我都想在鼠标光标下方绘制椭圆。当我稳定地移动鼠标而不是快得不可思议时,我注意到椭圆总是在鼠标轨迹后方几厘米处画出,并且只有在我停止移动光标时才会赶上椭圆。这在只有几个节点的场景图中。在我的Swing应用

  • 使用此示例,我想创建带有节点的TreeView,我可以拖动这些节点来更改它们的位置。 我试图实现这个例子,但我在这里遇到了一个问题: 我得到了

  • 在JavaFX中,我试图通过单击并拖动节点来移动它。如果节点不旋转,它工作得很好,但是当我旋转它时,它开始表现得很奇怪。 在45°左右,当我移动它时,它开始抖动,在60°时,它剧烈地来回抖动。在90°时,只要我开始移动节点,它就会飞离屏幕。 下面是我用来旋转和移动节点的代码。它来自连接到节点的鼠标侦听器。 编辑:这是一些示例输出,以及显示不同节点的图片。 未旋转且缓慢向左移动时的输出: 旋转时缓慢

  • 我是 GraphStream 的新手,并且已经构建了一个最小的应用程序,其中 GraphStream 2.0 图形嵌入到 Swing 应用程序中。 在我的应用程序中,当我尝试拖动节点时,鼠标指针显然偏移了大约一半的面板大小(垂直和水平)。 这是代码: 下图显示了在中心拖动矩形节点时的鼠标指针位置(以红色包围)。 关于这个问题的原因有什么想法吗? 编辑: 下面是一个简短的GIF动画,显示了问题(显示

  • 问题内容: 我试图在这个问题中创建一个类似于“奖杯轮”的可旋转节点。到目前为止,我具有甩尾功能,可以使用效果很好的UIPanGestureRecognizer在物理物体上添加角度脉冲。我也可以通过触摸停止旋转。 现在,我试图通过拖动或滑动手势来微调方向盘,这样,如果玩家对最终的效果不满意,就可以手动旋转/拖动/旋转它所喜欢的旋转方式。 目前,我将触摸的位置保存在touchesBegan中,并尝试在

  • 我正在尝试将一个矩形拖动到VBox,然后从VBox内部再次拖动它。 如果矩形被放置在目标VBox之外的任何位置,那么它应该将其位置恢复到它所属的位置:如果它是左VBox的子级,则将其重置回其中;如果它是右VBox的子级,则将其重置回右VBox内部。 第一部分工作正常,我可以将其拖到VBox并将其添加为子级。第二部分是我遇到问题的地方。 重现问题的步骤:<br>1)将左矩形拖动到右矩形的顶部(在VB