当前位置: 首页 > 知识库问答 >
问题:

JavaFX ChangeListener不总是工作

李谦
2023-03-14
worker.messageProperty().addListener((observable, oldValue, newValue) -> {
    ta_Statusbereich.appendText("\n" + newValue);
});
for (Integer i = 1; i <= 300; i++) {
    updateMessage(i.toString());
    System.out.println(i.toString());
}

为什么?是否有其他方法将消息文本附加到TextAres,也许使用绑定?

共有1个答案

曹泉
2023-03-14

message属性被设计为保存任务的“当前消息”的属性:即目标用例类似于状态消息。在这个用例中,如果在属性中存储了很短时间的消息从未被拦截,这并不重要。实际上,updateMessage()的文档指出:

对updateMessage的调用将合并并稍后在FX应用程序线程上运行,因此对updateMessage的调用,即使来自FX应用程序线程,也不一定会导致立即更新此属性,中间消息值可能会合并以保存在事件通知上。

(我的强调)。因此,简而言之,如果一些传递给updateMessage(...)的值很快被另一个值取代,那么它们实际上可能永远不会被设置为messageProperty的值。通常,每次在屏幕上呈现一个帧(每秒60次或更少)时,只能观察到一个值。如果您有一个重要的用例,您希望观察每一个值,那么您需要使用另一种机制。

for (int i = 1 ; i <= 300; i++) {
    String value = "\n" + i ;
    Platform.runLater(() -> ta_Statusbereich.appendText(value));
}
final int numThreads = 8 ;
Executor exec = Executors.newFixedThreadPool(numThreads, runnable -> {
    Thread t = Executors.defaultThreadFactory().newThread(runnable);
    t.setDaemon(true);
    return t ;
});

// ...

for (int i = 1; i <= 300; i++) {
    int value = i ;
    Task<String> task = new Task<String>() {
        @Override
        public String call() {
            // in real life, do real work here...
            return "\n" + value ; // value to be processed in onSucceeded
        }
    };
    task.setOnSucceeded(e -> ta_Statusbereich.appendText(task.getValue()));
    exec.execute(task);
}
BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();

Task<Void> task = new Task<Void>() {
    @Override
    public Void call() throws Exception {
        final int numMessages = 300 ;
        Platform.runLater(() -> new MessageConsumer(messageQueue, ta_Statusbereich, numMessages).start());
        for (int i = 1; i <= numMessages; i++) {
            // do real work...
            messageQueue.put(Integer.toString(i));
        }
        return null ;
    }
};
new Thread(task).start(); // or submit to an executor...

// ...

public class MessageConsumer extends AnimationTimer {
    private final BlockingQueue<String> messageQueue ;
    private final TextArea textArea ;
    private final numMessages ;
    private int messagesReceived = 0 ;
    public MessageConsumer(BlockingQueue<String> messageQueue, TextArea textArea, int numMessages) {
        this.messageQueue = messageQueue ;
        this.textArea = textArea ;
        this.numMessages = numMessages ;
    }
    @Override
    public void handle(long now) {
        List<String> messages = new ArrayList<>();
        messagesReceived += messageQueue.drainTo(messages);
        messages.forEach(msg -> textArea.appendText("\n"+msg));
        if (messagesReceived >= numMessages) {
            stop();
        }
    }
}
 类似资料:
  • 我目前使用的是Xcode 8.3.3,如果我使用的是UIWebView,我会遇到这个错误,您可以在下面看到,然后在某些项目中或某些时候WebView不工作,而在其他项目中它会工作。我已经用一个空项目对它进行了测试,是的,是UIWebView导致了这些问题。 objc[11182]:类PLBuildVersion在/Applications/xcode . app/Contents/Develope

  • 我试着用Google Location API在地图中定义地理位置,我使用genymotion和Lockito的智能位置库togheter来测试我的地理信息,但当我开始Lockito测试时,我的IntentService捕捉到了谷歌地理信息事件,错误代码为1000,在谷歌API for Android文档中,这意味着地理信息不可用错误,我使用genymotion和我的Moto G3进行测试,但结果

  • 我对Java非常陌生,在仔细阅读文档之后,我发现自己陷入了困境。 我有一个使用JavaFXMediaPlayer播放wav文件的小程序。我的播放器对象有一个currentTimeProperty,我希望在播放期间以分钟:秒为单位显示该属性的输出。 所以我在一个函数的末尾有这样一个函数,它接收我的wav文件并初始化播放器: 然后我有: 这很有效。在wav播放过程中,my以毫秒为单位随当前时间更新。问

  • 我正在做一个C程序,用厄拉多塞筛寻找质数 目前我有以下代码: C 这工作正常,即它说在1和100之间有25个素数(这是正确的)。但是,例如,如果我想知道前500个素数,它会说有118个,而实际上有95个。为了解决这个问题,我必须添加更多的倍数来删除,然后添加更多。 有没有一种方法可以使它更有效,而不仅仅是让它去除以前发现的素数的更多倍数?

  • 在使用流进行聚合时,Brian Goetz将使用stream.collect()填充集合与使用stream.foreach()进行相同的操作进行了比较,其中有以下两个片段: 根据我的理解,只有在流是并行的情况下,多个线程才能在forEach()中工作。但是,在给出的示例中,forEach()是在一个顺序流上操作的(没有调用parallelStream())。 那么,是forEach()总是并行工作

  • 我已经尝试了一段时间让smoothScrollToPositionFromTop()工作,但它并不总是滚动到正确的位置。 我有一个ListView(有10个条目)的布局,边上有10个按钮,所以我可以滚动到列表中的每个条目。通常,当我向后或向前滚动一个位置时,效果很好,但是当我试图向后或向前滚动超过3个位置时,ListView并不完全在所选位置结束。当它失败时,它通常会减少0.5到1.5个项目,并且