我有一个 JavaFX 应用程序,其中有一个并发任务。 当任务运行时,我想将来自 updateMessage() 的消息附加到 TextArea
因为绑定(bind)不会将新文本附加到 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 然后我在 ChangeListener 中添加了一个 println 并得到相同的结果,1,4,5,8,9 (结果是随机的,并不总是 1,4,5...)
为什么?是否有其他方法可以将消息文本附加到 TextAres,也许使用 bind ?
最佳答案
message 属性被设计为保存任务 的“当前消息”的属性:即目标用例类似于状态消息。在此用例中,仅在属性中存储很短时间的消息是否永远不会被截取都无关紧要。事实上,documentation for updateMessage()状态:
Calls to updateMessage are coalesced and run later on the FX application thread, so calls to updateMessage, even from the FX Application thread, may not necessarily result in immediate updates to this property, and intermediate message values may be coalesced to save on event notifications.
(我的重点)。因此,简而言之,传递给 updateMessage(...) 的某些值如果被另一个值快速取代,可能永远不会真正设置为 messageProperty 的值。通常,每次将一帧渲染到屏幕时(每秒 60 次或更少),您可以期望只观察到一个值。如果您的用例需要观察每个值,那么您需要使用另一种机制。
一个非常幼稚的实现将只使用 Platform.runLater(...) 并直接更新文本区域。我不推荐这种实现方式,因为您可能会因太多调用而淹没 FX 应用程序线程(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 应用程序线程上的区域。为确保您不会用过多的调用淹没 FX 应用程序线程,您应该在每帧渲染到屏幕时使用队列中的消息不超过一次。您可以使用 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();
}
}
}
关于JavaFX ChangeListener 并不总是有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31408363/
这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案
好的,所以我有了我正在使用的应用程序的这种方法,它可以在生产中使用。我的问题为什么这行得通?这是新的Ruby语法吗?defeditload_elements(current_user)unlesscurrent_user.role?(:admin)respond_todo|format|format.json{render:json=>@user}format.xml{render:xml=>@user}format.htmlendrescueActiveRecord::RecordNotFoundrespond_to_not_found(:json,:xml,:html)end
defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就
最好用一个例子来解释:文件1.rb:deffooputs123end文件2.rb:classArequire'file1'endA.new.foo将给出错误“':调用了私有(private)方法'foo'”。我可以通过执行A.new.send("foo")来解决这个问题,但是有没有办法公开导入的方法?编辑:澄清一下,我没有混淆include和require。另外,我不能使用正常包含的原因(正如许多人正确指出的那样)是因为这是元编程设置的一部分。我需要允许用户在运行时添加功能;例如,他可以说“run-this-app--includefile1.rb”,应用程序的行为将根据他在file1
我有以下数组:A=[1,2,3,4,5]B=[2,6,7,1]我想找到不相交的元素,如下:output=[3,4,5,6,7]我是这样实现的,output=A+B-(A&B)但它效率低下,因为我添加了两个数组,然后删除了公共(public)元素。它类似于查找不相交的元素。我能做得比这更好吗?如果是,怎么办? 最佳答案 如何只选择A中的元素而不是B中的元素以及B中的元素而不是A中的元素。(A-B)+(B-A) 关于arrays-在两个数组中查找不相交元素的有效方法是什么?,我们在Stack
当我刚刚运行middleman时服务,all.css编译得很好,只包含对+box-shadow(none)的调用:/*line1,/home/yang/asdf/source/stylesheets/content.css.sass*/div{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}但是当我构建网站时,我得到了这个Sass/Compass错误:$middlemanbuildSlim::EmbeddedEngineisdeprecated,itiscalledSlim::EmbeddedinSlim2.0
这个问题在这里已经有了答案:关闭11年前。PossibleDuplicate:RubyblockandunparenthesizedargumentsWhatisthedifferenceorvalueoftheseblockcodingstylesinRuby?我一直认为以下只是同一件事的两种表达方式:[1,2,3].collect{|i|i*2}[1,2,3].collectdo|i|i*2end但是我在我的一个ERB模板中发现了一些奇怪的行为,这两种语法似乎在做两件不同的事情。这段代码效果很好:m))}}%>但是当我将其重写为:m))endend%>...我最终得到了我的@men
编辑:更改了标题。我对两个部分是否相同不太感兴趣,而是如果它们在一定的公差范围内彼此共线。如果是这样,那么这些线应该聚集在一起作为一个单独的线段。编辑:我想有一个简短的说法:我试图以一种有效的方式将相似的线段聚集在一起。假设我有线段f(fx0,fy0)和(fx1,fy1)和g(gx0,gy0)和(gx1,gy1)这些来自计算机视觉算法边缘检测器之类的东西,在某些情况下,两条线基本相同,但由于像素容差而被视为两条不同的线。有几种情况f和g共享完全相同的端点,例如:f=(0,0),(10,10)g=(0,0),(10,10)f和g共享大致相同的端点和大致相同的长度,例如:f=(0,0.01