Java视图的可用性属性超出了GUI视图的范围 [英] Usability of JavaFX Properties outside the scope of the GUI view

查看:141
本文介绍了Java视图的可用性属性超出了GUI视图的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用JavaFX(Java8)工作一段时间后,我发现了属性非常有用,允许使用bean兼容变量绑定以使用计算树更新更改,例如:

After working some while with JavaFX (Java8) I had found the concept of Properties very useful, allowing to use bean compliant variables to be bound to update on changes using a calculation tree e.g.:

    class Person {
        StringProperty name;
        ...
    }

    Person owner;
    Person human;

    owner.name().bind(human.name());

允许将GUI控件绑定到模型,以便在更改时自动更新。

That allows to bind the GUI controls to the 'model', to automatically update on change.

所以我也开始使用 属性< T> 类中的类(我的数据对象,我正在进行功能操作)。但JavaFX是一个单线程GUI实现,只有在JavaFX线程中完成时,才允许设置链接到某些GUI控件的属性。否则将抛出异常:

So I also started to use the Property<T> class in the model (my data objects I am doing my functional operations). But the JavaFX is a single threaded GUI implementation and setting such a Property linked to some GUI controls is only allowed, if it is done in the JavaFX thread. Else an exception will be thrown:

  Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5

如果我现在开始编写多线程代码,我终于无法使用这些属性,即使我愿意。我无法在Platform.runLater()调用中封装每个更改以将其传递给JavaFX线程。

If I now start to write multithreaded code, I finally cannot use these Properties, even if I would love to. I cannot afford to encapsulate every change in a Platform.runLater() call to pass it to the JavaFX thread.

为什么JavaFX不提供线程安全的Property-Binding ?
(或者是吗?)

Why does JavaFX not provide a thread-safe Property-Binding? (Or does it?)

推荐答案


JavaFX属性的可用性超出了范围GUI视图

Usability of JavaFX Properties outside the scope of the GUI view

JavaFX属性绝对可以在GUI视图的范围之外使用。基本的 Oracle JavaFX绑定教程演示了这一点通过创建一个简单的非GUI java程序,该程序代表一个Bill对象,其中账单的总金额通过JavaFX属性公开。

JavaFX properties can definitely be used outside the scope of the GUI view. The basic Oracle JavaFX binding tutorial demonstrates this by creating a simple non-GUI java program which represents a Bill object where the total amount of the bill is exposed via a JavaFX property.


为什么JavaFX不提供线程安全的Property-Binding? (或者是吗?)

Why does JavaFX not provide a thread-safe Property-Binding? (Or does it?)

JavaFX不支持线程安全的属性绑定。可能它不支持线程安全属性绑定的原因是因为它不需要。

JavaFX does not support thread-safe property-binding. Probably the reason it does not support thread-safe property binding is because it does not need to.

虽然JavaFX内部有一个带有渲染线程,应用程序线程等的多线程体系结构,但在开发人员外部,它实际上只暴露了单个应用程序线程。从开发人员的角度来看,开发人员将他们的应用程序编码为单线程系统。开发人员和内部JavaFX实现可以假设一切都在单线程环境中运行,编码更简单(参见多线程工具包:失败的梦想?如何在实际不同的线程中运行两个JavaFX UI 以获取有关为什么这是案件)。知道它正在这样的环境中执行的属性实现也可以采用单线程架构并跳过可能使内置线程安全控件复杂化。

Although JavaFX internally has a multi-threaded architecture with a render thread, an application thread, etc., externally to developers it really only exposes the single application thread. From a developer point of view, the developer codes their application as a single threaded system. The developer and the internal JavaFX implementations can just assume that everything is running in a single-threaded environment and coding is much simpler (see Multithreaded toolkits: A failed dream? and How to run two JavaFX UI in actual different threads for some background information on why this is the case). The property implementation, knowing that it is executing in such an environment, can also assume a single threaded architecture and skip potentially complicating in-built thread safety controls.

JavaFX确实有为并发任务生成新线程的能力(并且还可以使用标准Java开发的许多并发工具中的任何一个。 JavaFX并发API确实能够以线程安全的方式反馈属性值(例如为任务执行完成的工作的百分比),但这是以非常特定的方式完成的。任务API具有用于修改此类属性的专用方法(例如 updateProgress )并在内部使用线程检查和调用,例如 Platform.runLater 以确保代码以线程安全的方式执行。

JavaFX does have the ability to spawn new threads for concurrent tasks (and any of the many concurrent facilities for standard Java development can also be used). The JavaFX concurrent API does have the ability to feed back property values (such as percentage of work done for task execution) in a thread safe manner, but that is done in a very specific way. The task API has specialized methods for modifying such properties (for example updateProgress) and internally it uses thread checks and calls such as Platform.runLater to ensure that code executes in a thread-safe manner.

因此,JavaFX并发实用程序无法通过JavaFX属性机制的内置功能实现线程安全,而是通过在并发实用程序实现中进行显式检查和调用来实现一组非常具体和有限的属性。即使这样,用户在使用这些实用程序时也必须非常小心,因为他们通常认为他们可以直接从并发任务中修改JavaFX GUI阶段属性(即使文档声明不应该这样做);如果使用标准的Java并发实用程序(如java.util.concurrent包)而不是javafx.concurrent,则需要同样谨慎。

So the JavaFX concurrency utilities don't achieve thread safety through in-built capabilities of the JavaFX property mechanism, but instead through explicit checks and calls inside the concurrency utility implementation for a very specific and limited set of properties. Even then, users have to be very careful when using these utilities as they often assume they can do things such as modify JavaFX GUI stage properties directly from within their concurrent tasks (even though documentation states that this should not be done); the same care needs to be taken if standard Java concurrent utilities like the java.util.concurrent package is used rather than javafx.concurrent.

有人可能会创建JavaFX属性机制的扩展,以便在线程安全环境中更好地运行,但是迄今为止没有人创建过这样的扩展。

It is possible that somebody could create an extension to the JavaFX property mechanism to better behave in thread safe environment, but nobody has created such an extension to date.


但是JavaFX是一个单线程GUI实现,如果在JavaFX线程中完成,则只允许设置链接到某些GUI控件的属性。

But the JavaFX is a single threaded GUI implementation and setting such a property linked to some GUI controls is only allowed, if it is done in the JavaFX thread.

问题的标题是GUI视图范围之外的JavaFX属性的可用性,但您描述的特定问题是这是一个非常具体的子集,我认为你有以下几种组合:

The title of the question is "Usability of JavaFX properties outside the scope of the GUI view", but the particular issue you describe is a pretty specific subset of this, where I think you have the following combination of things:


  1. 模型类的属性。

  2. 模型类中的属性可以由JavaFX应用程序线程或其他用户线程读取和写入。

  3. 模型类中的属性可以绑定到活动GUI元素,如TextField中的文本或屏幕上显示的标签。

开箱即用这不起作用因为JavaFX系统假定仅在JavaFX应用程序线程上读取或修改JavaFX GUI组件的属性。此外,在内部支持绑定和更改侦听器,属性本身需要维护要修改的侦听器和绑定属性的列表,并且这些列表可能假设它们只能从单个线程访问或修改。您可以通过使用Platform.runLater包装调用以将调用放在JavaFX应用程序线程上来确保每个读取或写入都在单个线程上进行解决,但是根据您的问题,这正是您所使用的那种代码。试图避免。

Out of the box this isn't going to work because the JavaFX system assumes that properties of JavaFX GUI components are only read or modified on the JavaFX application thread. Also, internally to support binding and change listeners, the properties themselves need to maintain lists of listeners and bound properties to modify, and these lists likely assume that they will only be accessed or modified from a single thread. You can perhaps work around this by ensuring that every read or write goes on a single thread by wrapping invocations using Platform.runLater to place the call on the JavaFX application thread, but from your question, this is exactly the kind of code which you are trying to avoid.

IMO对于我在上述几点中概述的用例,没有其他解决方案,必须使用Platform.runLater包装。您可以通过为属性访问和更新提供Facade方法(类似于JavaFX并发Task实现)来隐藏runLater调用的一些复杂性和样板,但是这样的系统实现起来可能有点复杂(特别是如果您想要实现整个属性/绑定子系统的通用解决方案,而不是像Task那样的几个特定属性的专用解决方案。

IMO for the use case I outlined in the points above, there is no other solution and Platform.runLater wrapping must be used. You can potentially hide some of the complexity and boilerplate for the runLater calls by providing facade methods for property access and updates (similar to the JavaFX concurrent Task implementation), but such a system is likely a bit complex to implement (especially if you want to achieve a generic solution for the entire property/binding subsystem, rather than a specialized solution for a couple of specific properties like Task has).

什么是JavaFX属性那么?

主要的现有用例是支持JavaFX GUI应用程序的基于绑定的GUI编程模型。 JavaFX属性广泛用于JavaFX API和使用该API的任何应用程序。

The primary existing use-case is for supporting the binding-based GUI programming model for JavaFX GUI applications. JavaFX properties are used extensively with the JavaFX API and any application which uses that API.

由于JavaFX现在包含在所有标准的新Oracle JDK发行版中,您还可以使用非JavaFX程序中的属性。例如,有关如何在 JPA实体bean中使用这些属性的讨论。根据我的经验,这些非JavaFX API用例目前非常少见。

As JavaFX is now included in all standard new Oracle JDK distributions, you can also use the properties from non-JavaFX programs. For instance, there are discussions on how to use these properties in JPA entity beans for instance. These non-JavaFX API use-cases are currently pretty rare in my experience.

尽管JavaFX属性和绑定包位于javafx包命名空间内,但它们并不依赖于其他JavaFX包。在未来的模块化JDK(例如Java 9)中,有可能让Java程序依赖于JavaFX属性和绑定模块,并且不依赖于其他模块来进行JavaFX GUI开发(这可能对某些无头服务器系统,它们是许多Java应用程序的主要部署目标。

Although the JavaFX properties and binding packages are within the javafx package namespace, they do not depend on other JavaFX packages. In a future modular JDK, such as Java 9 is proposed to be, it would be possible to have a Java program depend on a JavaFX property and binding module and not have any dependency on other modules for JavaFX GUI development (which might be useful for certain headless server systems, which are the primary deployment target for many Java applications).

最初为其他JavaFX工具设置了类似的设计,例如时间轴和转换,以便通过时间轴基于时间安排任务的实时Java系统可以使用JavaFX中的动画/时间轴模块而不依赖于JavaFX系统的其余部分(但我不确定原始设计是否已经延续到今天,因此可能不再可能,并且动画模块的基本脉冲是通常键入60fps的最小刻度,可能锁定在屏幕刷新率,具体取决于实现)。

A similar design was originally setup for other JavaFX facilities such as the timelines and transitions, such that a real-time Java system with time based scheduling of tasks via Timelines could make use of an animation/timeline module from JavaFX without depending upon the rest to the JavaFX system (but I am not sure that original design was carried through to today, so that might not really be possible anymore and the base pulse of the animation module is usually keyed to the minimum tick of 60fps perhaps locked at a screen refresh rate depending on the implementation).

JavaFX属性不是Java的属性管理的通用解决方案,但是它们可能是迄今为止我见过的最接近,最完整的解决方案。理想的(我记得JavaFX项目负责人Richard Bair所说的)是,属性功能将构建到Java编程语言中,因此支持不仅来自API,还来自改进的语言语法。也许未来的某些Java版本(例如10+)可能具有这些设施。当然,这是一个古老的讨论,可能追溯到Java语言和JDK规范的开头。尽管如此,世界并不理想,JavaFX属性机制(即使它具有庞大的语法和缺乏内置的线程安全支持)仍然是许多应用程序的有用工具。另请注意,Scala通过ScalaFX可以扩展其他语言,这使得JavaFX属性机制看起来像是该语言语法的一部分。

JavaFX properties are not the generic solution to property management for Java, but they are probably the closest, most complete implementation of such a solution that I have seen so far. The ideal (as I recall the JavaFX project lead Richard Bair stating), is that property functionality would be built into the Java programming language, so the support comes not only from an API, but from improved language syntax. Perhaps some future Java version such as 10+ might have facilities such as these. Of course, that is an old discussion probably dating back to the beginning of the Java language and JDK specifications. Still, the world is not ideal and the JavaFX property mechanism (even with it's kind of bulky syntax and lack of in-built support for thread-safety), is still a useful tool for many applications. Also note that there are extensions for other languages as as Scala via ScalaFX which make the JavaFX property mechanism seem like it part of the syntax for that language.

第三方库,例如 EasyBind ,增强JavaFX属性机制以更好地支持编程范例,例如功能反应式编程。

Third Party libraries such as EasyBind, enhance the JavaFX property mechanism to better support programming paradigms such as functional reactive programming.

目前,如果我想在JavaFX程序中广泛使用属性类型工具,我可能会将它基于JavaFX属性和(可能)EasyBind和 ReactFX 的组合,因为它似乎成为Java的最佳解决方案。

For now, if I wanted to make extensive use of property type facilities in a JavaFX program, I would probably base it on a combination of JavaFX properties and (potentially) EasyBind and ReactFX, as that seems to be the best solution for Java.

我不会在高度并发的环境中使用这样的解决方案,因为底层库中缺少线程安全支持,线程非划分。属性基于对可变对象的副作用更改,这在多线程程序中是很难推理的。即使修改了内部属性实现以允许对属性进行线程安全读/写,我也不确定它是否会是一个很好的方法。对于需要在并发子任务之间进行大量通信的高度并发系统,使用另一种编程范例,例如 Actors (例如 akka / erlang )或沟通顺序流程可能比绑定属性更合适。

I would not use such a solution in a highly concurrent environment where threading is non-compartmentalized due to the lack of thread-safety support in the underlying libraries. Properties are based upon side-effect changes to mutable objects, which is a pretty difficult thing to reason about in multi-threaded programs. Even if the internal property implementation was modified to allow thread-safe read/writes on properties, I'm not sure that it would be such a great approach. For highly concurrent systems requiring a lot of communication between concurrent subtasks, use of another programming paradigm such as Actors (e.g. akka/erlang) or communicating sequential processes may be more appropriate than bound properties.

这篇关于Java视图的可用性属性超出了GUI视图的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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