【问题标题】:JavaFX: Moving a circle with ThreadsJavaFX:用线程移动一个圆圈
【发布时间】:2019-10-17 20:16:07
【问题描述】:

我正在尝试创建动画,但没有使用 TranslateTransition 等内置功能。在 Anchor Pane 上,我创建了一个圆圈,我希望它沿着这样的线不断移动:

 public void initialize()  {  
        MyThread task = new MyThread();
        new Thread(task).start();  
    }
class MyThread extends Task<Integer>
{
    @FXML
    Circle myCircle;
    @Override
    protected Integer call() throws Exception
    {
        int i= 737; //starting position
        while(true)
        {
            ((Node) myCircle).setLayoutX(i);
            i--;
            if(i%109==0) //ending position
                i=737;

        }
    }

}

但它根本不动。我是 javaFX 线程的新手,所以我真的不知道我做错了什么。但是当我像这样打印一些数字时,它工作得很好:

class MyThread extends Task<Integer>
{
    @Override
    protected Integer call() throws Exception
    {
        for(int i=0; i<10;i++)
        {
            count(i);
            count10(i);
        }

    protected void count(int i)
    {
        System.out.println(i);
    }

    protected void count10(int i)
    {
        System.out.println(10*i);
    }

}

【问题讨论】:

    标签: java multithreading user-interface javafx


    【解决方案1】:

    JavaFX 节点只能从 JavaFX 应用程序线程中修改。您正在从后台线程修改 layoutX 属性,这会产生不可靠的结果。

    您可以更新value 属性并使用Task.value 属性的侦听器来为您处理同步:

    class MyThread extends Task<Integer> {
    
        @Override
        protected Integer call() throws Exception {
            final int minX = (737 / 109) * 109; // use rounding of integer division to find greatest int <= 737 divisible by 109
    
            while(true) {
                for (int i = 737; i >= minX; i--) {
                    updateValue(i);
                }
            }
        }
    
    }
    
    MyThread task = new MyThread();
    task.valueProperty().addListener((o, oldValue, newValue) -> circle.setLayoutX(newValue.doubleValue()));
    new Thread(task).start();
    

    请注意,此代码的结果可能非常不可预测:更新之间没有延迟,因此更新绑定时的值可能是随机的...


    否则你必须使用Platform.runLater 来更新GUI,但这对你的代码来说相当棘手,因为你更新的频率足够高,以至于JavaFX 无法应付所有Runnables已提交。

    我确实建议使用像 AnimationTimer 这样的 JavaFX 类。提供这些类以供使用。尝试自己实现这样的事情可能比它的价值更麻烦,尤其是作为没有经验的程序员。

    【讨论】:

    • 是的,问题是我正在尝试制作更复杂的动画,而我认为我无法通过内置动画来做到这一点。这段代码只是为了测试 JavaFX 中的线程。
    • 当我尝试你的代码时,我也收到了java.lang.RuntimeException: Circle.layoutX : A bound value cannot be set.
    • @NotStudent 出于某种原因,AnchorPane 即使没有设置约束,也会重新定位孩子。您要么需要使用 Pane 作为父级,要么使用监听器进行更新(稍后编辑到问题中的代码)。
    猜你喜欢
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多