栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaFX ChangeListener并非始终有效

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFX ChangeListener并非始终有效

message
属性被设计为包含的“当前消息”的属性,
task
即目标用例类似于状态消息。在此用例中,仅在非常短的时间内存储在属性中的消息不会被截取并不重要。实际上,有关
updateMessage()
状态的文档:

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

(我的重点)。因此,简而言之,如果传递给它们的某些值很快被另一个值所取代

updateMessage(...)
messageProperty
则可能实际上不会设置为这些值。通常,每次将一帧渲染到屏幕上时,您都只能观察到一个值(每秒60次或更少)。如果您有一个重要的用例,那就要观察每个值,那么您就需要使用另一种机制。

一个非常幼稚的实现将只使用

Platform.runLater(...)
并直接更新文本区域。我不推荐这种实现方式,因为您冒着太多调用淹没FX
Application Thread的风险(
updateMessage(...)
合并调用的确切原因),使UI 无法响应。但是,此实现如下所示:

for (int i = 1 ; i <= 300; i++) {    String value = "n" + i ;    Platform.runLater(() -> ta_Statusbereich.appendText(value));}

另一种选择是使每个操作成为一个单独的任务,并在某个执行程序中并行执行它们。附加到每个任务

onSucceeded
处理程序中的文本区域。在此实现中,结果的顺序不是预先确定的,因此,如果顺序很重要,则这不是适当的机制:

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
,从阻止队列中提取消息,并将其放置在FX
Application线程的文本区域中。为确保您不会在FX
Application线程中进行过多的调用,每帧渲染到屏幕上的消息应最多消耗一次队列中的消息。您可以
AnimationTimer
为此使用一个:
handle
保证每个帧渲染都调用一次它的方法。看起来像:

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


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/496241.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号