删除节点时 UI 不更新

Posted

技术标签:

【中文标题】删除节点时 UI 不更新【英文标题】:UI not updating when nodes are being removed 【发布时间】:2019-11-15 14:04:29 【问题描述】:

我正在尝试从我的窗格中逐个删除所有节点,以便我可以看到被删除的每一行。为此,我创建了一个新线程并使用了任务类并将方法 delWalls() 包装在一个 Platform.runLater() 。然后我使用 Thread.sleep 认为它会减慢循环速度,因此我可以看到 UI 更新,因为每一行都被删除但是会发生什么是整个 UI 冻结,然后在循环完成后所有节点都消失了?有没有办法解决这个...谢谢

*所有节点都是线

 //loop calls delWalls() 1458 times to delete all 1458 nodes sequentailly
    Task task = new Task<Void>() 
        @Override
        public Void call() 
            Platform.runLater(() -> 
                try 
                    for (int i = 0; i <= 1458 - 1; i++) 
                        Thread.sleep(2);


                        delWalls();
                    
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            );

            return null;
        
    ;
    new Thread(task).start();


    

//delWalls方法每次调用都会删除一个节点。

  public void delWalls() throws InterruptedException 

    pane.getChildren().remove(0);
 

【问题讨论】:

for-loopThread.sleep 违反了框架的单线程特性——这些操作是在“主线程”的上下文中执行的,所有的 UI 工作也都在这里完成,所以在循环结束并且runLater 回调退出之前什么都不会改变 您将需要找出更好的更新/动画方法,并且由于 JavaFX 是为动画而构建的,因此您可以使用多种可能性,也许从 Creating Transitions and Timeline Animation in JavaFX 开始,或者,因为我来自 Swing 背景,类似于this,它使用“timer”风格的回调 是的,谢谢这位老板让它现在与时间线一起工作 :) 干杯sssss 糟糕,很抱歉在发布我的答案之前没有看到您的评论。 【参考方案1】:

正如@MadProgrammer 所说,您需要使用 Timeline 才能获得所需的效果。 下面是如何完成它的快速示例演示。点击“添加”依次添加节点,10个节点全部添加完毕后,点击“删除”,即可逐个删除。

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class RemoveNodes_Demo extends Application 
    @Override
    public void start(Stage stage) throws Exception 
        FlowPane pane = new FlowPane();
        pane.setVgap(10);
        pane.setHgap(10);

        Button button1 = new Button("Add Nodes");
        button1.setOnAction(e->
            Timeline timeline = new Timeline(new KeyFrame(Duration.millis(400), x -> 
                StackPane sp = new StackPane();
                sp.setMinSize(100,100);
                sp.setStyle("-fx-background-color:black,red;-fx-background-insets:0,2;");
                pane.getChildren().add(sp);
            ));
            timeline.setCycleCount(10);
            timeline.play();
        );

        Button button2 = new Button("Remove Nodes");
        button2.setOnAction(e->
            if(!pane.getChildren().isEmpty())
                int count = pane.getChildren().size();
                Timeline timeline = new Timeline(new KeyFrame(Duration.millis(400), x -> 
                   if(!pane.getChildren().isEmpty()) 
                      pane.getChildren().remove(0);
                   
                ));
                timeline.setCycleCount(count);
                timeline.play();
            
        );
        VBox root = new VBox(button1, button2,pane);
        root.setSpacing(10);
        Scene sc = new Scene(root, 600, 600);
        stage.setScene(sc);
        stage.show();
    

    public static void main(String... a) 
        Application.launch(a);
    

【讨论】:

非常感谢,我遇到了越界错误,但这解决了我在 if(!pane.getChildren.isEmpty()) 中看到的问题。再次感谢 是的.. 从技术上讲,我还应该在删除节点之前添加一个空检查(以防多个时间线试图删除)。更新了代码。

以上是关于删除节点时 UI 不更新的主要内容,如果未能解决你的问题,请参考以下文章

Element UI tree 递归删除选中节点生成树

element UI tree 递归删除树节点

ArcEngine的线要素删除一些节点后如何更新

AWS Elastic Beanstalk:如何更改节点命令?在最近的更新中删除了容器选项?

递归删除资源树 Ztree

从图中删除节点或重置整个默认图