JavaFX:通过线程移动圆圈

时间:2019-06-01 14:35:56

标签: java multithreading user-interface javafx

我正在尝试创建动画,但是没有使用诸如TranslateTransition之类的内置功能。在“锚定窗格”上,我创建了一个圆,我希望它沿着这样的直线不断移动:

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

}

1 个答案:

答案 0 :(得分: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无法处理所有{{ 1}}个提交。

我建议您改用AnimationTimer之类的JavaFX类。这些类可供使用。自己尝试实现这样的事情可能会带来更多的麻烦,尤其是作为一个没有经验的程序员。