我有一个JavaFX 8应用程序,希望允许一个任务修改两个不同的UI元素。据我所知,如果我有一个标签要修改,我可以用mylabel绑定到标签。textProperty()。绑定(mytask.messageProperty())并在任务中使用updateMessage()。
如何使用两种不同的任意类型执行此操作?我已经查看了并发和JavaFX文档中的示例,但对我来说,它们并没有很好地解释这一点。
我知道一个任务本质上有Message(String)、gres(Double/long)、Title(String)和Value(user定义的)属性,但是如果我想要两个或多个我自己的任意类型的属性来控制UI元素呢?(并且想避免使用run延迟()。)
我可以在任务上创建任意属性吗?我觉得我错过了一些明显的东西。
忠告
仅当您需要自定义属性的任务上的属性样式接口时,才使用下面的解决方案。通常,许多应用程序不需要这样的接口和单个Platform.run稍后调用而不是公开自定义属性就足够了。
解决方案
您可以使用与任务的message属性相同的习惯用法。我将把相关代码复制并粘贴到这个答案中。请注意,此解决方案将通过原子引用“合并更新,这样我们就不会淹没事件队列”。这个解决方案并不违背JavaFX的一般绑定特性,如果使用得太频繁,也不会给主线程带来太多消息。但是,由于它合并了更新,因此并非每个属性更新都会引发属性更改。每个脉冲最多只触发一次属性更改。
private final StringProperty message = new SimpleStringProperty(this, "message", "");
@Override public final String getMessage() { checkThread(); return message.get(); }
@Override public final ReadOnlyStringProperty messageProperty() { checkThread(); return message; }
/**
* Used to send message updates in a thread-safe manner from the subclass
* to the FX application thread. AtomicReference is used so as to coalesce
* updates such that we don't flood the event queue.
*/
private AtomicReference<String> messageUpdate = new AtomicReference<>();
/**
* Updates the <code>message</code> property. 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.
* <p>
* <em>This method is safe to be called from any thread.</em>
* </p>
*
* @param message the new message
*/
protected void updateMessage(String message) {
if (isFxApplicationThread()) {
this.message.set(message);
} else {
// As with the workDone, it might be that the background thread
// will update this message quite frequently, and we need
// to throttle the updates so as not to completely clobber
// the event dispatching system.
if (messageUpdate.getAndSet(message) == null) {
runLater(new Runnable() {
@Override public void run() {
final String message = messageUpdate.getAndSet(null);
Task.this.message.set(message);
}
});
}
}
}
// This method exists for the sake of testing, so I can subclass and override
// this method in the test and not actually use Platform.runLater.
void runLater(Runnable r) {
Platform.runLater(r);
}
// This method exists for the sake of testing, so I can subclass and override
// this method in the test and not actually use Platform.isFxApplicationThread.
boolean isFxApplicationThread() {
return Platform.isFxApplicationThread();
}
其他问题的答案
这是来自类任务的源代码?
是的。这是任务的源代码。
所以你是说唯一的方法是用额外的属性扩展任务类,就像上面的任务中所做的那样?
若您希望自定义任务中的自定义属性可以同时修改,那个么是的,您需要对任务进行子类化。但这与将自定义属性添加到您定义的任何其他类(或扩展另一个现有类以添加属性)没有太大区别。唯一的区别是额外的机制,以确保执行发生在正确的线程上,并在需要时合并。
第二个主题,您似乎一开始就说偶尔调用runLater是一种可以接受的方式?
是的,站台。runLater()是在任务和JavaFX UI线程之间传递消息的推荐方式(如任务javadoc中所示)。
这些属性提供了任务和对象之间的松散耦合,这些对象可能通过观察者模式依赖于任务。如果不需要松耦合,那么就不需要专门的属性(尽管它们有时很有用,而且绑定起来也很简单,因为JavaFXAPI的其余部分(如标签的文本)都是基于属性的)。
问题内容: 我有一个带有文本字段和按钮的简单fxml。如果文本字段为空,我想禁用按钮。所以我在控制器中插入如下内容: ..那很好。问题是当我添加第二个文本字段时,如果其中一个文本字段为空,希望禁用我的按钮。那该怎么办?我尝试了以下操作,但这不起作用: 问题答案: 可以通过以下方式绑定到布尔表达式:
我有一个带有文本字段和按钮的简单fxml。如果文本字段为空,我想禁用按钮。所以我在我的控制器中插入如下内容: ..这很好用。问题是,当我添加第二个文本字段时,如果其中一个文本字段为空,我希望禁用我的按钮。那怎么办呢?我尝试了以下方法,但不起作用:
我正在开发一个简单的Java程序来完成一些简单的mySQL内容。它有一个用JavaFX制作的小GUI。 GUI的控制器有一个SimpleBoleanProperty,我们称之为X,它指示到数据库的连接状态。我将一些简单的东西绑定到它,比如按钮的disableProperty so send querys,如果没有连接,应该禁用它。到现在为止,一直都还不错。 我有一个标签,用于执行以下操作: 如果X
我遵循了许多链接,找到了在表视图中显示复选框的解决方案。但我无法更改表视图中复选框的值。 链接如下:如何在JavaFX中将CheckBox添加到TableView中 模型类: FXML文件: 控制器类: 输出:
主要内容:绑定选项,双向绑定,高级别绑定,低级别绑定,UI控件和域模型之间的绑定JavaFX绑定同步两个值:当依赖变量更改时,其他变量更改。 要将属性绑定到另一个属性,请调用bind()方法,该方法在一个方向绑定值。 例如,当属性A绑定到属性B时,属性B的更改将更新属性A,但不可以反过来。 绑定选项 JavaFX提供了许多绑定选项,以便在域对象和GUI控件中的属性之间进行同步。 我们可以在JavaFX的Properties API中使用以下三种绑定策略: Java Bean上
我想做的是: 我有一个JavaFX窗口,我通过拖动不断改变它的宽度和高度。然后的文本具有以下格式: 例子: 我想使用绑定,而不是使用2(两)个ChangeListeners来实现这一点。 我也读过这个问题JavaFX绑定到多个属性