欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Kotlin编写JavaFX的顺滑

时间:2023-06-19
如丝般顺滑的Kotlin+JavaFX

项目代码库前言

谁会读这篇文章写作目的 Kotlin桌面开发

JavaFxKotlin开发工具 Kotlin+JavaFX的形状

HelloFXKtMVVMJavaFX例子程序设计

主程序界面设计Model设计ViewModel 结论 项目代码库

项目代码

前言 谁会读这篇文章 致力于成为Kotlin桌面程序员的新手Kotlin爱好者想开发点桌面GUI来炫耀或者练习JavaFX爱好者 写作目的 把自己最近学习的心得记录下来,置于外部存储器对初学者有一点点帮助能够启发社区来投入JavaFX桌面开发 Kotlin桌面开发

Kotlin主要是为解决Android而开发的JVM编程语言,但是Kotlin的生命力使其迅速突破移动端。也有人说Kotlin四处出击,又是JVM又是Javascript,又是Native,没一个足够成熟,除提供语法糖之外并没有什么意义。但是我们作为用户,不需要去考虑那么多复杂的玩意。简单地说,试一试,好用就用。毕竟Talk is cheap, just show the code.

JavaFx

JavaFX 官方网站:JavaFX

“JavaFX是一个开源的下一代客户端应用平台,用于桌面、移动和嵌入式系统,建立在Java之上。它是由许多个人和公司合作完成的,目标是为开发丰富的客户端应用程序制作一个现代、高效和功能齐全的工具包。”

Kotlin开发工具

目前用于开发Java的IDE普遍提供插件进行Kotlin开发。当然,最为方便的应该试试Jetbrains公司的Intelli IDEA,因为Kotlin就是他们公司的崽。

免费的社区版也就够用。

Kotlin最顺滑的地方就是Kotlin调用Java库非常简单,无缝调用加上语法糖,简直比Java自己调用还简单。

Kotlin+JavaFX的形状 HelloFXKt

还是拿26行的JavaFX程序,HelloFX.java,作为开始。

package hellofximport javafx.application.Applicationimport javafx.scene.Sceneimport javafx.scene.control.Labelimport javafx.scene.layout.StackPaneimport javafx.stage.Stageclass HelloFX : Application() { override fun start(stage: Stage) { val javaVersion = System.getProperty("java.version") val javafxVersion = System.getProperty("javafx.version") val l = Label("Hello, JavaFX $javafxVersion, running on Java $javaVersion.") val scene = Scene(StackPane(l), 640.0, 480.0) stage.scene = scene stage.show() }}fun main(args: Array) { Application.launch(HelloFX::class.java, *args)}

程序大同小异,并没啥不同的。main函数从类里面拿出来,launch的调用也有一点点改变。去掉public、new、extends,增加override;set方法变成属性赋值。还有字符串模板,写+和${}也没有很大区别。能看懂Java的基本上也能看懂Kotlin。

而且,上面的代码是用Jetbrains Intelli IDEA自动转化Java代码得到的,改动非常少(只有main方法的部分)。

MVVM

但是有Kotlin之后,我们可以用干净利索点的方式来写。

微软帮助

MVVM模式有三个核心组件:模型、视图和视图模型。每一个都有不同的作用。下图显示了这三个组件之间的关系。
除了了解每个组件的职责外,了解它们如何相互作用也很重要。在高层次上,视图 "知道 "视图模型,而视图模型 "知道 "模型,但模型不知道视图模型,而视图模型也不知道视图。因此,视图模型将视图与模型隔离开来,并允许模型独立于视图来发展。

使用MVVM模式的好处有以下几点:

如果有一个现有的模型实现封装了现有的业务逻辑,那么改变它可能会很困难或有风险。在这种情况下,视图模型作为模型类的适配器,使你能够避免对模型代码做出任何重大的改变。开发人员可以为视图模型和模型创建单元测试,而不使用视图。视图模型的单元测试可以行使与视图所使用的完全相同的功能。应用程序的UI可以不修改业务代码的情况下被重新设计。在开发过程中,设计师和开发人员可以独立地、同时地在他们的组件上工作。设计师可以专注于视图,而开发人员可以在视图模型和模型组件上工作。

有效使用MVVM的关键在于理解如何将应用代码纳入正确的类中,以及理解这些类是如何互动的。

JavaFX例子

我们把Hellofx程序做一点点小改动,增加一个按钮。

点击这个按钮,原来的文本标签变成显示JavaFX和Java的版本。

程序设计

JavaFX的主程序为Application类不变。这个类显示View作为GUI用户界面,数据存储在Model中,ViewModel作为数据和界面解耦的部分存在。

主程序

主程序维持JavaFX应用的通用结构。继承Application,实现start方法,在这个方法中创建Model对象,ViewModel对象,Scene对象,显示在屏幕上。

import javafx.application.Applicationimport javafx.scene.Sceneimport javafx.stage.Stageclass HelloFX : Application() { override fun start(stage: Stage) { val m = Model() val vm = ViewModel(m) val root = getRoot(vm.versionText, vm::updateVersionText) val scene = Scene(root, 640.0, 480.0) stage.scene = scene stage.show() }}fun main(args: Array) { Application.launch(HelloFX::class.java, *args)}

程序中,界面的元素为Scene对象构造函数中的root,从这里看到,root为一个函数的范围值,这个函数的参数包括一个文本属性,一个函数。

下面就是界面设计,实际上也就是View多对应的那个函数的实现。

界面设计

界面包括一个Label和一个Button。View中处理界面的组合方式,处理界面的对齐方式,处理一切与数据不相关的部分。

fun textLabel(t: SimpleStringProperty): Node{ return Label(t.value).apply { textProperty().bind(t) }}fun updateButton(clickAction: () -> Unit): Node = Button("Check").apply { setonAction { clickAction() }}fun getRoot(text: SimpleStringProperty, clickAction: () -> Unit): Parent = VBox(10.0).apply { children.add(textLabel(text)) children.add(updateButton(clickAction)) alignment = Pos.CENTER}

可以看到,getRoot调用两个函数来产生文本标签和按钮,这两个参数,一个绑定(下次把这个翻译出来)到标签的文本属性,一个函数绑定到按钮的事件。

这样的方式,在JetPack Compose中称为声明式界面设计。完全没有假设别的东西。View部分只对一个文本属性SimpleStringProperty和一个() -> Unit的函数提出要求。这就是MVVM中核心的要素,分割责任。这个部分可以任意更改,任意变更,只需要满足设计条件:

界面跟踪一个文本的变化;界面出发一个函数调用。

这种方式保证了充分的内聚性。

Model设计

这里的数据模型非常简单。考虑到目前的交互是单向的,Model只需要提供数据,并没有反馈数据。

data class Model( val javaVersion: String = System.getProperty("java.version"), val javafxVersion: String = System.getProperty("javafx.version"))

ViewModel

ViewModel沟通Model和Application,因此其构造函数包含Model的实例作为参数。

import javafx.beans.property.SimpleStringPropertyclass ViewModel(private val m: Model) { val versionText = SimpleStringProperty("Hello!") fun updateVersionText() { versionText.value = "Hello, JavaFX ${m.javafxVersion}, running on Java ${m.javaVersion}." }}

结论

通过一个特别简单的例子,可以看到JavaFX+Kotlin之后,界面的开发是多么的顺滑。

上面的程序有几个特点:

界面不需要知道任何ViewModel或者Model的细节,也不需要维护相应的对象引用;界面用函数调用的形式来实现,通过绑定来明确其交互的效果,语义和语法都非常清晰;界面的设计可以单独完成,并且自由更改;Model的部分不需要考虑任何可视化和人机交互,只需要单独考虑业务逻辑;Model可以单独开发,自由更改;交互的业务逻辑在ViewModel中实现;ViewModel持有Model对象的引用;当Model的接口改变时,需要修改ViewModel的代码,因此Model和ViewModel是紧耦合;View和其他部分是松耦合,只与Application耦合,不依赖于程序的任何其他部分;Model和其他部分是松耦合,不依赖于程序中的任何部分。最终的界面交互逻辑和业务交互逻辑的关联由Application来维护。

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。