为 StackPane 对象创建具有绝对坐标的路径过渡

2023-12-02

OrangeBlock是一个橙色块,里面有文字。它被实现为StackPane其中包含矩形顶部的文本。 (这种方法在StackPane 的文档.)

我已经放置了一个OrangeBlock在坐标 (100, 80) 处,现在我正在尝试使其顺利移动到某个目标坐标。不幸的是,我的道路上遇到了一个令人讨厌的障碍:

Bumpy PathTransition

由于某种原因,坐标在PathElements 是相对于橙色块进行解释的。

为什么是这样?我怎样才能让我的OrangeBlock沿着绝对坐标的路径旅行?下面的最小工作示例。

import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class PathTransitionExample extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();

        OrangeBlock block = new OrangeBlock(60, 40);
        block.relocate(100, 80);
        root.getChildren().add(block);

        PathTransition transition = newPathTransitionTo(block, 460, 320);

        primaryStage.setScene(new Scene(root, 600, 400));
        primaryStage.show();
        transition.play();
    }

    private static PathTransition newPathTransitionTo(OrangeBlock block,
            double toX, double toY) {
        double fromX = block.getLayoutX();
        double fromY = block.getLayoutY();

        Path path = new Path();
        path.getElements().add(new MoveTo(fromX, fromY));
        path.getElements().add(new LineTo(toX, toY));

        PathTransition transition = new PathTransition();
        transition.setPath(path);
        transition.setNode(block);
        transition.setDelay(Duration.seconds(1));
        transition.setDuration(Duration.seconds(2));

        return transition;
    }

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

    private static class OrangeBlock extends StackPane {
        public OrangeBlock(int width, int height) {
            Rectangle rectangle = new Rectangle(width, height, Color.ORANGE);
            Text text = new Text("Block");
            getChildren().addAll(rectangle, text);
        }
    }
}

出于好奇,我调试了 JavaFX 代码。看来您没有找到正确的解决方案。发生的情况如下:

PathTransition 代码有一个 interpolate(double frac) 方法,其中包括:

cachedNode.setTranslateX(x - cachedNode.impl_getPivotX());
cachedNode.setTranslateY(y - cachedNode.impl_getPivotY());

impl_getPivotX() 和 impl_getPivotY() 方法包含以下内容:

public final double impl_getPivotX() {
    final Bounds bounds = getLayoutBounds();
    return bounds.getMinX() + bounds.getWidth()/2;
}

public final double impl_getPivotY() {
    final Bounds bounds = getLayoutBounds();
    return bounds.getMinY() + bounds.getHeight()/2;
}

因此 PathTransition 始终使用节点的中心进行计算。换句话说,这适用于 e。 G。一个 Circle 节点,但不包含 e。 G。一个矩形节点。此外,您还需要layoutBounds,因此必须在边界可用后创建PathTransition。

您可以在 PathTransition 代码中看到,计算都是相对的,并且已经涉及布局位置。所以在你的 lineTo 中你必须考虑这一点。

值得注意的是,LineTo 类有一个方法 setAbsolut(boolean)。然而它并不能解决你的问题。

所以我对你问题的解决方案是

  • 在主阶段可见后创建 PathTransition
  • 修改moveTo和lineTo参数

这对我有用(我添加了一个矩形形状来直观地识别正确的边界):

public class PathTransitionExampleWorking2 extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {

        Group root = new Group();

        Rectangle rect = new  Rectangle( 100, 80, 460-100+60, 320-80+40);
        root.getChildren().add(rect);

        OrangeBlock block = new OrangeBlock(60, 40);
        block.relocate( 100, 80);

        root.getChildren().add(block);

        primaryStage.setScene(new Scene(root, 600, 400));
        primaryStage.show();

        // layout bounds are used in path transition => PathTransition creation must happen when they are available
        PathTransition transition = newPathTransitionTo(block, 460, 320);
        transition.play();
    }

    private static PathTransition newPathTransitionTo(OrangeBlock block, double toX, double toY) {

        double fromX = block.getLayoutBounds().getWidth() / 2;
        double fromY = block.getLayoutBounds().getHeight() / 2;

        toX -= block.getLayoutX() - block.getLayoutBounds().getWidth() / 2;
        toY -= block.getLayoutY() - block.getLayoutBounds().getHeight() / 2;

        Path path = new Path();
        path.getElements().add(new MoveTo(fromX, fromY));
        path.getElements().add(new LineTo(toX, toY));

        PathTransition transition = new PathTransition();
        transition.setPath(path);
        transition.setNode(block);
        transition.setDelay(Duration.seconds(1));
        transition.setDuration(Duration.seconds(2));

        return transition;
    }

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

    private static class OrangeBlock extends StackPane {
        public OrangeBlock(int width, int height) {
            Rectangle rectangle = new Rectangle(width, height, Color.ORANGE);
            Text text = new Text("Block");
            getChildren().addAll(rectangle, text);
        }
    }
}

编辑:另一种解决方案是使用它而不是 MoveTo 和 LineTo:

public static class MoveToAbs extends MoveTo {

    public MoveToAbs( Node node) {
        super( node.getLayoutBounds().getWidth() / 2, node.getLayoutBounds().getHeight() / 2);
    }

}

public static class LineToAbs extends LineTo {

    public LineToAbs( Node node, double x, double y) {
        super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
    }

}

注意:在创建primaryStage之后,您仍然需要创建PathTransition。

编辑:这是另一个例子,块移动到鼠标单击的位置:

public class PathTransitionExample extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {

        Group root = new Group();

        OrangeBlock block = new OrangeBlock(60, 40);
        block.relocate(100, 80);
        root.getChildren().add(block);

        Label label = new Label( "Click on scene to set destination");
        label.relocate(0, 0);
        root.getChildren().add(label);

        Scene scene = new Scene(root, 600, 400);

        scene.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<Event>() {

            PathTransition transition;

            {
                transition = new PathTransition();
                transition.setNode(block);
                transition.setDuration(Duration.seconds(2));

            }

            @Override
            public void handle(Event event) {

                transition.stop();

                setPositionFixed(block.getLayoutX() + block.getTranslateX(), block.getLayoutY() + block.getTranslateY());

                double x = ((MouseEvent) event).getX();
                double y = ((MouseEvent) event).getY();

                Path path = new Path();
                path.getElements().add(new MoveToAbs( block));
                path.getElements().add(new LineToAbs( block, x, y));

                transition.setPath(path);
                transition.play();

            }

            private void setPositionFixed( double x, double y) {
                block.relocate(x, y);
                block.setTranslateX(0);
                block.setTranslateY(0);
            }

        });

        primaryStage.setScene( scene);
        primaryStage.show();

        PathTransition transition = newPathTransitionTo(block, 460, 320);
        transition.play();

    }

    private static PathTransition newPathTransitionTo(OrangeBlock block, double toX, double toY) {

        Path path = new Path();
        path.getElements().add(new MoveToAbs( block));
        path.getElements().add(new LineToAbs( block, toX, toY));

        PathTransition transition = new PathTransition();
        transition.setPath(path);
        transition.setNode(block);
        transition.setDelay(Duration.seconds(1));
        transition.setDuration(Duration.seconds(2));

        return transition;
    }

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

    private static class OrangeBlock extends StackPane {
        public OrangeBlock(int width, int height) {
            Rectangle rectangle = new Rectangle(width, height, Color.ORANGE);
            Text text = new Text("Block");
            getChildren().addAll(rectangle, text);
        }
    }

    public static class MoveToAbs extends MoveTo {

        public MoveToAbs( Node node) {
            super( node.getLayoutBounds().getWidth() / 2, node.getLayoutBounds().getHeight() / 2);
        }

    }

    public static class LineToAbs extends LineTo {

        public LineToAbs( Node node, double x, double y) {
            super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
        }

    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为 StackPane 对象创建具有绝对坐标的路径过渡 的相关文章

  • JavaFX 使用动画最小化和最大化未装饰的舞台

    我在这个问题中使用已接受的答案 JavaFX 最小化未修饰的阶段 https stackoverflow com questions 26972683 javafx minimizing undecorated stage正确最小化我的应用
  • FXML load() 期间出现 JavaFX IllegalAccessException

    我有一个由以下代码调用的对话框窗口 DialogController是使用模式对话框窗口的辅助类 它主要将控制器引用与其窗口捆绑在一起 void handleServicesEdit ActionEvent event throws IOE
  • 使用 PixelWriter 在 JavaFX Canvas 上进行透明绘图

    有谁知道为什么使用drawImage 在Canvas上进行透明度绘制工作得很好 但在PixelWriter上却根本不起作用 我最初认为这可能与画布 上下文上的混合或其他模式 设置有关 但还没有任何运气 我需要每个像素的可变透明度 而不是整个
  • JavaFX TabPane - 每个选项卡一个控制器

    我是 Fx 新手 我有一个带有 10 个选项卡的 TabPanel 每个选项卡都有很多控件 图表 按钮等 我想要的是为每个选项卡分配一个控制器 SceneBuilder 只让我为整个视图分配一个控制器 我的意思是 只有顶部面板 根 具有 控
  • 如何在JavaFX中获得一个小的ProgressBar

    我正在尝试获得一个类似 iTunes 的进度条 该进度条非常小 高度约为 5 像素 但我似乎无法低于 19 或 20 像素 我尝试在周围的窗格上设置 fx max height 但没有效果 请注意 这个值确实会改变高度 我只是不能让它小于大
  • JavaFX 中的内部框架

    我找到了这个内部框架的例子 http docs oracle com javase tutorial uiswing components internalframe html http docs oracle com javase tut
  • 在 Jar 中为 Gluon Scene Builder 11.00 创建自定义控件

    我想在可执行 jar 文件中创建自定义控件 然后在 Gluon Scene Builder 11 00 中使用 我需要知道如何做到这一点 我尝试了几种形式 但在场景生成器中导入 jar 时我的控件没有出现 我正在使用 IntelliJ Co
  • 确定 JavaFX 中是否消耗了事件

    我正在尝试使用 JavaFX 中的事件处理来做一些非滑雪道的事情 我需要能够确定手动触发事件后是否已消耗该事件 在以下示例中 正确接收了合成鼠标事件 但调用 Consumer 不会更新该事件 我对此进行了调试 发现 JavaFX 实际上创建
  • 如何在 JavaFX 中将 FontAwesome 升级到版本 5

    我有一个使用 FontAwesome 图标的 JavaFX 我想使用新版本 5 但似乎已经不起作用了 这是一个用 Groovy 编写的简单演示应用程序 可与旧版 FontAwesome 一起使用 import javafx applicat
  • JavaFX 中的 fx:id 和 id: 有什么区别?

    也许是一个真正的新手的问题 我开始通过阅读以下教程在 FMXL 应用程序中使用场景生成器学习 JavaFX http docs oracle com javase 8 javafx get started tutorial fxml tut
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • 如何从 JavaFX 中的另一个控制器类访问 UI 元素?

    我有一个使用 NetBeans 8 编写的 JavaFX Java 8 应用程序 没有SceneBuilder 我的应用程序有一个主窗口 该窗口有自己的 FXML 文件 primary fxml 和自己的控制器类 FXMLPrimaryCo
  • 使用多个值过滤 JFX TableView

    我目前正在尝试过滤我的数据TableView using FilteredList with predicate 我有2个ComboBoxes来过滤值 我的表包含Result Each Result has a Student that S
  • ListChangeListener wasPermutated 块

    ListChangeListener 的 JavaDoc 提供了用于处理更改的模板 但是 我不知道如何处理排列 对于每个索引 我都可以找到该项目的新索引在哪里 但我不知道如何处理它 这是一个独立于编程语言的难题 ObservableList
  • 如何加载图像文件到ImageView?

    我试图在从文件选择器中选择图像文件后立即显示该图像文件 文件选择器仅限于 png 和 jpg 文件 所选文件存储在文件类型的变量中 为此 我设置了一个 ImageView 我希望用这个新文件设置图像 唯一的问题是它的类型是文件而不是图像 如
  • javafx组合框下拉菜单从屏幕边缘跳出

    我有最新版本的 java 8 40 和 javaFX 我有一个包含 10 个项目的复选框 我编译并运行该程序 如果我将程序窗口移至监视器屏幕的底部 下拉列表将从监视器屏幕中消失 无法将项目点击出屏幕 相反 如果我尝试使用场景生成器 2 0
  • 从 MS Access 中提取 OLE 对象(Word 文档)

    我有一个 Microsoft Access 数据库 其中包含一个包含 Microsoft Word 文档的 OLE 对象字段 我试图找到代码来检索保存在 OLE 对象中的文件 以便用户可以从我的 JavaFx 应用程序中的按钮下载它 但没有
  • JavaFX颜色选择器的语言

    有没有办法改变语言ColorPicker的文本 例如 自定义颜色 当前颜色 新颜色 色相 饱和度 亮度 不透明度 保存 使用 取消 编辑 以下答案适合那些需要更多内容的人exotic语言 如果您使用其中之一 de es fr it ja k
  • Gluon 移动 iOS 音频播放器

    由于 JavaFx Media 尚未移植到移动平台 任何人都可以帮助我使用本机 iOS APi 来播放声音 mp3 文件 该文件将存储在我的 gluon 项目的 main resources 文件夹中 在 Android 上 我们可以轻松地
  • mobileapplication.mobileevent BACK_BUTTON_PRESSED

    我的两个视图中有 2 个 Android 本机音频实例 当用户按下后退按钮并离开视图时 我试图让音频停止 因为它不会自动发生 我查看了文档并看到了 MobileEvent 类 我尝试实现它的构造函数 但没有成功 这是我的第一个应用程序 为此

随机推荐

  • filepicker.io Javascript API 调用导致不安全的 javascript 错误

    我目前正在使用 AngularJS 我想从我的上传控制器调用 filePicker pickAndStore 对 filepicker io API 函数的任何调用都会导致 不安全的 Javascript 尝试 错误 请求访问的帧具有 ht
  • SecurityError:操作不安全。使用 Htmlcanvas [重复]

    这个问题在这里已经有答案了 尝试转换图像我drag并将我的画布元素放入 PNG 或 Jpeg 照片中 有点类似于 Polyvore 的情绪板概念 这样我就可以在一张 PNG 或 Jpeg 照片中一次性查看放置在画布上的所有图像 这样我就可以
  • 在Javascript中实现优先级队列的有效方法?

    优先级队列对于每个条目都有一个优先级值和数据 因此 当向队列添加新元素时 如果它具有比集合中已有元素更高的优先级值 它就会冒泡到表面 当调用 pop 时 我们会获取具有最高优先级的元素的数据 在 Javascript 中 这种优先级队列的有
  • 使用未定义的 webpack 类捆绑 js 文件

    我将以下文件内容捆绑在一起 a js class BaseC doIt console log this class A extends BaseC b js class B extends BaseC var b new B b doIt
  • JSF:如何防止构建阶段由于递归而导致的堆栈溢出(尽管进行了渲染测试)

    对于没有在专用测试用例中抽象这个问题表示歉意 我希望来自真实项目的示例足够简单来描述问题 我有一个 JavaEE JPA2 JSF Web 应用程序 其中每个 Entity 元素 或子类 都有一个模板化 view xhtml 页面和一个标准
  • 使用 CI hook 设置公共变量

    我有几个常用变量 我想使用钩子来设置它们 例如 我有一个 post controller constructor 挂钩 在其中我想执行一些逻辑来设置用户主文件夹 public function post controller constru
  • Enterprise Library 3.1 日志格式化程序模板 - 包括 URL 请求

    我们有一个使用 Ektron v8 0 构建的自定义 Web 应用程序 该应用程序使用 EL 3 1 并且日志记录配置中的格式模板配置如下
  • 如何提高 MongoDB 批量性能?

    我有这个对象 其中包含一些元数据和大量项目 我曾经将其存储在 mongo 中 并通过以下方式查询它 unwind荷兰国际集团的数组 然而 在极端情况下 阵列变得如此之大 以至于我遇到了 16MB BSON 限制 所以我需要将数组的每个元素存
  • 在 cython 中使用函数指针作为模板参数包装 C++ 代码

    我试图将以下用 C 编写的声明包装在 cython 中 template
  • 创建新类与使用导出 const 之间的差异

    Setup BabelJS es2015 反应 第一阶段 Webpack 反应 还原 CommonJS 和 ES6 的新功能 我知道对象实例和方法的静态容器之间的区别 但我不确定它们在分离到模块时的行为如何 所以我想知道返回实例之间有什么区
  • 为什么 Java main() 方法接受 String args 数组?

    既然它可能是 Java 语言中使用最广泛的方法之一 为什么它必须接受字符串数组并且没有它就无法工作 例如 我总是可以忍受 public static void main over public static void main String
  • 使用客户端证书进行智能卡身份验证

    我有一个第三方 Web 应用程序 现在我的经理想要将智能卡身份验证添加到某些页面 而不是整个应用程序 并返回证书信息 我的想法是向这些页面添加按钮 并在onclick事件中 我将进行客户端证书身份验证 其中将出现一个证书选择窗口 后跟 PI
  • Vuetify:使 v-navigation-drawer 占据左上角的所有空间,而不是 v-app-bar

    我有一个 VuetifyJS v3 页面 其中包含v app bar and v navigation drawer两者都在场 并且都与app道具集 这v app bar占据从左上角延伸的所有水平空间 这v navigation drawe
  • 捕捉表格图像

    我有一个带有控件的表单 我需要捕获该表单以进行图像处理 请帮我 谢谢 Control cntrl previously declared and populated Bitmap bmp new Bitmap cntrl Width cnt
  • 在 C++ 项目中使用 clang 作为库

    我正在尝试使用 clang 作为库 但我不确定如何链接 Makefile 中的文件 尝试以下位置的 ASTVisitor 代码 https clang llvm org docs RAVFrontendAction html 这是我的Mak
  • Vimeo 上传 API - 尝试删除票证时出现“无效状态”错误

    我按照官方 Vimeo Upload 文档一步步操作 可断点续传的 HTTP PUT 上传 但在最后一步 删除了上传链接 我总是收到 HTTP 500 无效状态 响应 什么使所有过程无效 我已经尝试了一切但没有成功 相关问题 Vimeo A
  • SSIS C# 脚本不兼容

    我最近接管了基于 SSIS ETL 的流程 由于一些许可问题 我不得不从 Data Tools 2013 升级到 2015 大部分项目都在升级中幸存下来并且运行良好 然而 在两个包中 我有一个非常简单的 C 方法 脚本转换 来解析一些导致一
  • 何时使用接口而不是抽象类,反之亦然?

    这可能是一个通用的 OOP 问题 我想根据接口和抽象类的用法对它们进行一般比较 什么时候需要使用接口 什么时候需要使用抽象类 我写了一篇关于此事的文章 抽象类和接口 总结 当我们谈论抽象类时 我们正在定义对象类型的特征 指定物体是什么 当我
  • AngularJS:循环 POST 请求并将每个索引传递到相关响应中

    我正在尝试使用 AngularJS 执行多个 http POST 请求 并且我需要创建一个成功完成请求的对象 如下所示 var params 1 2 3 url i done for i in params url dir params i
  • 为 StackPane 对象创建具有绝对坐标的路径过渡

    OrangeBlock是一个橙色块 里面有文字 它被实现为StackPane其中包含矩形顶部的文本 这种方法在StackPane 的文档 我已经放置了一个OrangeBlock在坐标 100 80 处 现在我正在尝试使其顺利移动到某个目标坐