【问题标题】:NullPointerException while fast updating TextField快速更新 TextField 时出现 NullPointerException
【发布时间】:2016-12-14 11:34:05
【问题描述】:

我正在开发一个应用程序,该应用程序在定向文件夹中搜索一些文件并将它们打印在 TableView<myFile> foundFilesList 中,该文件存储在 Main 类中。 myFile 只是扩展了File 一点。搜索是使用后台线程中的服务完成的,它将找到的数据放入ObservableList<myFile> filesOfUser。 我想在同一视图中显示 TextField foundFilesAmount 中的当前查找文件数量,其中包含文件的 TableView 位于 - ResultsView

为此,我为foundFilesList 添加了一个ListChangeListenerResultsView 控制器,它使用方法setText 打印filesOfUser 的当前大小。它看起来像:

Main.filesOfUser.addListener(new ListChangeListener<myFile>() {
        @Override
        public void onChanged(Change<? extends myFile> c) {
               while (c.next()){
                  if (c.wasAdded())
                        setCounter(c.getAddedSize());    
              }
        }
});

void setCounter (int number) 仅包含

  int currValue = Integer.valueOf(foundFilesAmount.getText());
  foundFilesAmount.setText(String.valueOf(currValue + number));

现在问题出在哪里。具有当前查找文件数量的文本字段更新得非常快,并且从一开始它就停止了。在控制台中,我看到很多来自 JavaFX 应用程序线程的重复 NullPointerException's。其内容:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.text.PrismTextLayout.getRuns(PrismTextLayout.java:236)
at javafx.scene.text.Text.getRuns(Text.java:317)
at javafx.scene.text.Text.updatePGText(Text.java:1465)
at javafx.scene.text.Text.impl_updatePeer(Text.java:1500)
at javafx.scene.Node.impl_syncPeer(Node.java:503)
at javafx.scene.Scene$ScenePulseListener.synchronizeSceneNodes(Scene.java:2290)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2419)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)

我尝试在使用 setText 之前设置某种延迟,例如仅在第 5 次、第 10 次、第 15 次更新等之后更新 foundFilesAmount 中的值。但如果搜索工作时间更长,异常仍然存在扔了。

是否有正确的方法来显示当前找到的文件数量,包含真实数量并且不会导致太多异常?

提前致谢。

【问题讨论】:

    标签: java events javafx observablelist


    【解决方案1】:

    正确的方法是不在应用程序线程以外的线程上进行 UI 的更新。这可能会导致渲染/布局问题。

    您可以使用Task 对更新进行更新:

    Task<ObservableList<myFile>> task = new Task<
    Task<ObservableList<myFile>>() {
        @Override
        protected ObservableList<myFile> call() throws Exception {
            ObservableList<myFile> files = FXCollections.observableArrayList();
    
            while (...) {
                ...
                files.add(...);
                updateMessage(Integer.toString(files.size()));
                ...
            }
    
            return files;
        }
    };
    task.setOnSucceeded(evt -> tableView.setItems(task.getValue()));
    Thread t = new Thread(task);
    textField.textProperty().bind(task.messageProperty());
    t.setDaemon(true);
    
    t.start();
    

    【讨论】:

    • 搜索本身是由SimpleFileVisitor 在单独的类中完成的。从任务我只能通过Files.walkFileTree 开始搜索。如果我尝试使用控制器中的方法来更新我的 textField,在这个单独的类中,我会得到NullPointerException,因为 textField 没有在其他线程中初始化。这就是我在那里使用ListChangeListener 的原因。
    【解决方案2】:

    试试这样的:

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                // update your JavaFX controls here
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多