我有一个JavaFX应用程序,并且有一个并发任务。在任务运行时,我想将来自updateMessage()的消息附加到TextArea
因为绑定不会将新文本追加到TextArea,所以我使用了ChangeListener
worker.messageProperty().addListener((observable, oldValue, newValue) -> {
ta_Statusbereich.appendText("\n" + newValue);
});
这是可行的,但并非每一项更改都有效。我用System.out.println()检查了一下,并将任务从1计数到300
for (Integer i = 1; i <= 300; i++) {
updateMessage(i.toString());
System.out.println(i.toString());
}
任务中的这个println()给我我想要的1,2,3,4,5,6,7,8等等,但是我的TextArea显示1,4,5,8,9然后我在其中添加了一个println
ChangeListener并获得相同的结果1,4,5,8,9(结果是随机的,并不总是1,4,5 …)
为什么呢?还有其他方法可以将消息文本附加到TextAres,也许可以使用bind?
该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();
}
}
}
我在Android上使用Firebase云消息,遇到了以下问题。当处理应用程序在后台时收到的通知时发生。文件说明如下: 我正在测试的通知是一个显示消息通知(不是数据通知),它也有一个有效负载。
我对Java非常陌生,在仔细阅读文档之后,我发现自己陷入了困境。 我有一个使用JavaFXMediaPlayer播放wav文件的小程序。我的播放器对象有一个currentTimeProperty,我希望在播放期间以分钟:秒为单位显示该属性的输出。 所以我在一个函数的末尾有这样一个函数,它接收我的wav文件并初始化播放器: 然后我有: 这很有效。在wav播放过程中,my以毫秒为单位随当前时间更新。问
下面是片段。请注意,我已经恢复到以前的提交,因此丢失了最近的修改,但请查看我编写的代码,然后才注意到始终等于0() 以下是当检测到活动后按: 以下是NoteActivity接收结果调用的方式。 null 我在我的项目上浪费了很多重要的时间,只是想知道是什么使resultCode和requestCode的值丢失了我发送的值。 任何帮助和指导都将不胜感激。非常感谢!
我正在使用power shell控制台运行以下power外壳脚本: 这将打印错误。然后继续并打印“创建的新对象”和“结束”。所以我假设这是一个非终结性错误。 但是,如果我将try catch块放在新对象周围,如下所示: 在这种情况下,捕获块被击中并写入异常消息。 我的问题是: < li >这是一个非终止错误吗?这看起来像是一个非终止性错误,因为在错误之后继续执行(当没有try catch块时)。
问题内容: 我正在尝试将java8 forEach循环内的布尔变量更改为true,这是非最终的。但是我遇到了以下错误:在封闭范围内定义的必需局部变量必须是final或有效的final。 如何解决这个错误? 代码: 这是我在函数中创建的变量。 现在,当我尝试更改它时: 我收到错误消息:封闭范围中定义的必需局部变量必须是final或有效的final。 为什么会出现此错误,以及如何解决? 问题答案: 您
问题内容: 遇到这个问题(有点烦人),我正在尝试查找集合中的所有记录,而不显示(或显示)特定字段(得分)。这只是一个示例,并不能反映我的实际代码,但是问题总是可以重现的。我要排除的字段非常大,我只是试图生成可用记录的菜单。 像这样的命令 始终返回每个字段,而不是触发mongodb中的排除/包含。我不需要担心什么,因为模板可以控制哪些数据呈现为html?仍然感觉无论如何数据都已传输到客户端。并显示在