JavaFX JavaFX开始时是一种名为JavaFX script的脚本语言。Sun Microsystems打算在较小程度上与Adobe Flex(现在称为Apache Flex)和Microsoft Silverlight竞争。
2010年,在同时收购Sun的Oracle的Java One上,甲骨文宣布它将在保留API的同时停止该语言的开发。随着2014年发布的Java 8的发布,JavaFX成为了Swing API的正式后继产品:Swing API从那时起才得到错误修复。
过去,JavaFX一直包含在Oracle JDK中,直到版本11。
但是它一直是一个单独的项目,也可以与JDK分开安装。
—从使用Gluon工具启动JavaFX项目开始 与Swing相比,JavaFX添加了应用程序抽象。以下是JavaFX API的概述:
此外,您可以采用两种不同的方法来创建JavaFX用户界面:
这是针对同一应用程序的前者和后者的示例。
Tornado FX
Kotlin允许改进Java API,以提供更好的开发人员体验。我们可以自己做。但是Tornado FX项目已经解决了这个问题。
这是API的鸟瞰图:
与普通的JavaFX相比,Tornado FX有很多好处。这里是其中的一些。
组件和布局DSL
与Groovy一样,Kotlin允许创建可用的DSL。与Groovy不同,默认情况下,创建的DSL是类型安全的。您可以找到我之前关于DSL的实验中的两个。
同样,Tornado FX通过DSL提供JavaFX的所有现成组件和布局。这是一个看起来像的例子:
vbox { text("Name") textfield() button("Button").setOnAction { println("Button pressed") } }
一些布局允许更复杂的配置。例如,JavaFX提供了GridPane类似于AWT的布局GridbagLayout。您需要将配置作为GridPaneContraints每个布局元素的对象传递。这是一个示例:
GridbagLayout
override val root = gridpane { padding = insets(space) textfield { gridpaneConstraints { columnIndex = 0 fillWidth = true hGrow = Priority.ALWAYS marginBottom = space } } button("Button") { gridpaneConstraints { columnIndex = 1 hAlignment = HPos.RIGHT marginBottom = space } } textfield { gridpaneConstraints { rowIndex = 1 fillWidth = true hGrow = Priority.ALWAYS } } textfield { gridpaneConstraints { columnRowIndex(1, 1) fillWidth = true hGrow = Priority.ALWAYS marginLeft = space } } }
尽管看起来不那么可读,但是IDE可以提供巨大的帮助。使用IntelliJ IDEA,您可以折叠不重要的位:
我倾向于在可能的情况下为每个组件创建专用的类,而不是使用在实例化时配置的泛型类。它不适用于现有DSL,因为我需要用自己的DSL进行补充。
控制器
Tornado FX的控制器以MVC模式实现C部分。他们负责封装业务逻辑。UI线程永远不要运行长时间运行的任务,因为它将使它无响应。由于控制器可以执行此类任务,因此您应根据具体情况进行决策。最后,您可以将一个控制器(见下文)作为单例注入到其他组件中。
该API不强制执行任何要求。由开发人员根据上述准则设计控制器。 例如,这是一个控制器,当它收到另一种事件时将触发一个事件:
class PathModelController : Controller() { init { subscribe<DirectoryPathUpdatedEvent> { fire(PathModelUpdatedEvent(it.path)) } } }
Tornado FX的控制器可以注入视图中。这种方法将视图与逻辑结合在一起。我宁愿换一种方式:将视图注入控制器。因此,有可能以不同的逻辑重用UI组件。现有设计允许在不同的UI组件内重用相同的逻辑,这种逻辑的使用频率要低得多。
依赖注入
Tornado FX提供依赖注入。该API提供了两种方式来注入依赖项:
inject()
class MyView: View("My View") { val myController: MyController by inject() val myController2 by inject<MyController>() }
find()
class MyView: View("My View") { val myController = find(MyController::class) val myController2 = find<MyController>() }
请注意,inject()在使用View和Controller,但你需要使用find()其他类。
View
Controller
Event Bus
TornadoFX提供了一个单例作用域的事件总线。它的用法不过是古典。
事件类必须从FXEvent超类继承。TornadoFX需要设置用于管理事件的线程,无论是应用线程还是后台线程。长时间运行的任务应在后台线程上运行。
Component提供fire()将事件推送到总线的功能。它还提供了register()通知事件接收的功能,按类型过滤。
看起来像这样:
class FooEvent: FXEvent(BackgroundThread) class BarEvent: FXEvent(BackgroundThread) class Dummy { init { subscribe<FooEvent> { println(it) } } fun bar() { fire(BarEvent()) } }
结论
在开发了一个简单的演示应用程序之后,我对JavaFX和Tornado FX都没有意见。需要更多经验。我喜欢嵌入式事件总线,但是不喜欢控制器和UI组件之间的关系设计。
在所有情况下,如序言中所述,Swing不会获得任何更新。无论您是否喜欢,JavaFX都是可用选项的一部分。
原文链接:http://codingdict.com