JavaFX:Task的两个绑定属性 [英] JavaFX: two bound properties for Task

查看:148
本文介绍了JavaFX:Task的两个绑定属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JavaFX 8应用程序,并希望允许任务修改两个不同的UI元素。据我了解,如果我有一个要修改的Label,我可以使用mylabel.textProperty()。bind(mytask.messageProperty())绑定到Label并在任务中使用updateMessage()。

I have a JavaFX 8 application and want to allow a Task to modify two different UI elements. As I understand it, if I had a single Label to modify, I could bind to the Label with mylabel.textProperty().bind(mytask.messageProperty()) and use updateMessage() in the Task.

如何使用两种不同的任意类型执行此操作?我查看了并发和JavaFX文档中的示例,但对我来说,他们没有很好地解释这一点。

How can I do this with two different arbitrary types? I've looked at the examples in the concurrency and JavaFX docs but to me they do not explain this well.

我理解一个任务本身就有Message(String),Progress (double / long),Title(String)和Value(用户定义)属性,但是如果我想要两个或更多我自己的任意类型的属性来控制UI元素,该怎么办? (并且希望避免使用runLater()。)

I understand a Task inherently has Message(String), Progress(double/long), Title(String), and Value(user defined) properties, but what if I want two or more arbitrarily typed properties of my own for controlling UI elements? (And want to avoid using runLater().)

我可以在任务上创建任意属性吗?我觉得我错过了一些明显的东西。

Can I create arbitrary properties on a Task? I feel I am missing something obvious.

推荐答案

建议

如果您的任务需要属性样式界面来定制属性,请仅使用下面的解决方案。通常,许多应用程序不需要这样的接口和单个 Platform.runLater 调用而不是公开自定义属性就足够了。

Only use the solution below if you require a property style interface on your task for a customized property. In general, many applications do not require such an interface and a single Platform.runLater call rather than exposing a custom property will suffice.

解决方案

您可以使用与消息属性 任务。我只是将相关代码复制并粘贴到这个答案中。请注意,此解决方案将通过 AtomicReference 。此解决方案不会违反JavaFX的一般绑定特性,并且如果经常使用,则不会为主线程导致大量消息。但是,因为它合并了更新,所以不是对属性的每次更新都会触发属性更改。每个仅触发属性更改一次脉冲

You can use the same idiom as is used for the message property of a Task. I'll just copy and paste relevant code into this answer. Note that this solution will "coalesce updates such that we don't flood the event queue", by means of an AtomicReference. This solution does not go against the general bind nature of JavaFX and does not cause a lot of messages for the main thread if used too often. However, because it coalesces updates, not every update to the property will fire a property change. Property changes are only fired at most once per pulse.

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

其他问题的答案


这是来自类Task的源代码吗?

this is the source code from class Task?

是。这是来自任务的源代码


所以你说的唯一方法是扩展Task类如上面的任务中所做的其他属性?

So you're saying the only way is to extend the Task class with additional properties like is done in Task above?

如果你想在可以同时修改的自定义任务中使用自定义属性,那么是的,你需要子类任务。但这与将自定义属性添加到您定义的任何其他类(或扩展另一个现有类以添加属性)实际上没什么不同。唯一的区别是额外的机制,以确保执行在正确的线程上发生,并在需要时合并。

Well if you want custom properties in a custom Task that can be concurrently modified, then yes you need to subclass task. But this really not much different than adding custom properties to any other class you define (or extending another existing class to add properties). The only difference is the extra machinery to ensure that executions occur on the correct thread and are coalesced if needed.


第二个主题,你似乎在开始时说偶尔调用runLater是一种可以接受的方法吗?

Second topic, you also seem to say at the start that occasionally calling runLater is an acceptable way to do it?

是的, Platform.runLater()是推荐的在任务和JavaFX UI线程之间发送消息的方式(如任务javadoc )。

Yes, Platform.runLater() is the recommended way to message between tasks and the JavaFX UI thread (as demonstrated in the Task javadoc).

这些属性提供了任务和对象之间的松散耦合,这可能依赖于任务观察者模式。如果您不需要松散耦合,那么您不需要特别需要属性(尽管它们有时可以很有用并且很容易绑定,因为JavaFX API的其余部分,例如标签的文本,是基于属性的) 。

The properties provide for a loose-coupling between the task and objects which may rely on the task through an observer pattern. If you don't require the loose-coupling, then you don't specifically require properties (though they can sometimes be useful and simple to bind to, as the rest of the JavaFX API, such as a label's text, is property based).

这篇关于JavaFX:Task的两个绑定属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆