在JavaFX中在GUI中显示多条消息的推荐方法是什么?
显而易见的是创建一个TextArea
并添加消息。但是因为我在一些CPU密集型计算中生成了它们,所以它们来自不同的线程。在许多答案中,我读到TextArea
只能从主GUI线程访问,因此我使用LinkedBlockingQueue
作为Producer / Consument接口。但是当我尝试使用Timer
的{{3}}附加邮件时,我遇到了更多错误,如下所示:
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)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.Scene$ScenePulseListener.synchronizeSceneNodes(Scene.java:2289)
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)
我认为这个问题可能会使FX应用程序线程充斥着过多的消息。但必须有一些推荐的方法来做到这一点。正确?
MCVE:
public class MCVE extends Application {
@Override
public void start(Stage primaryStage) {
TextArea ta = new TextArea();
StackPane root = new StackPane();
root.getChildren().add(ta);
Scene scene = new Scene(root, 800, 650);
primaryStage.setScene(scene);
primaryStage.show();
Run.ta = ta;
new Thread(new Run()).start();
public static void main(String[] args) {
launch(args);
}
static class Run implements Runnable{
public static TextArea ta;
@Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
ta.appendText("lahsdvl lefwq gwlqwkjgl kqwldfwkhevf.");
}
}
}
}
如果你将字符串添加到BlockingQueue(而不是附加在Run
中),然后将&amp;在Application Thread中轮询它们,你仍然会得到相同的异常。
答案 0 :(得分:1)
您可以使用Platform#runLater(Runnable)
从另一个线程更新GUI:
将来某个未指定的时间在JavaFX应用程序线程上运行指定的Runnable。可以从任何线程调用的此方法将Runnable发布到事件队列,然后立即返回给调用者。 Runnables按照发布顺序执行。传递给runLater方法的runnable将在任何Runnable传递给后续的runLater调用之前执行。如果在JavaFX运行时关闭后调用此方法,则将忽略该调用:将不会执行Runnable并且不会抛出异常。
注意:应用程序应避免使用过多的待处理Runnable来充斥JavaFX。否则,应用程序可能会无响应。鼓励应用程序将多个操作批量处理为更少的runLater调用。此外,应尽可能在后台线程上执行长时间运行的操作,从而释放JavaFX应用程序线程以进行GUI操作。
按如下方式调整Run
:
static class Run implements Runnable {
public static TextArea ta;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Platform.runLater(() -> ta.appendText("Lorem ipsum.\n"));
}
}
}
另请查看以下相关问题: