/
Super charged JavaFX  with Kotlin and TornadoFX Super charged JavaFX  with Kotlin and TornadoFX

Super charged JavaFX with Kotlin and TornadoFX - PowerPoint Presentation

briana-ranney
briana-ranney . @briana-ranney
Follow
347 views
Uploaded On 2018-09-30

Super charged JavaFX with Kotlin and TornadoFX - PPT Presentation

v17 Introduction Developer at SYSE Norwegian hosting company Project lead for TornadoFX and FXLauncher Why TornadoFX JavaFX is a UI toolkit not a framework JavaFX is powerful but verbose ID: 683197

tornadofx val person data val tornadofx data person age customer view javafx code button save param tablecolumn root views

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Super charged JavaFX with Kotlin and To..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Super charged JavaFX

with Kotlin and TornadoFX

v1.7Slide2
IntroductionDeveloper at SYSE – Norwegian hosting company

Project lead for TornadoFX and FXLauncherSlide3
Why TornadoFX?

JavaFX is a UI toolkit, not a frameworkJavaFX is powerful, but verboseKotlin presents some unique opportunities for APIsSlide4
Statically typed JVM language from JetBrainsMore concise syntax, less noise from types/declarations

Specific DSL language constructsSlide5
GoalsReduce boilerplate, but never hide JavaFX APIs

Add commonly needed componentsWizard, Forms, DataGrid, ViewModel, Validation, ListMenu, Drawer, Workspace ++Improve existing componentsData Driven TreeView, TableView

Row Expansion, Auto Complete ComboBoxBeautiful, understandable, refactorable code!Slide6
Key Features

Type Safe BuildersType Safe CSSWorkspace Business Framework (RCP)MVC / MVP / MVVM and similar UI patternsDependency InjectionEventBusLive reloading of Views and CSSREST Client and JSONSlide7

Code comparisonJavaFX: Create a TableView

with two columnsTableView<Customer> table = new TableView<>(customers);TableColumn<Customer, String> firstNameColumn = new TableColumn<>(

"First Name"

);firstNameColumn.setCellValueFactory(param -> param.getValue().firstNameProperty());TableColumn<Customer, String> lastNameColumn = new TableColumn<>("Last Name");lastNameColumn.setCellValueFactory(param -> param.getValue().lastNameProperty());table.getColumns

().addAll(

firstNameColumn, lastNameColumn

);Slide8

tableview

(customers) { column("First Name", Customer::firstNameProperty) column("Last Name", Customer::lastNameProperty)

}

Code comparisonTornadoFX: Create a TableView with two columnsSlide9
Code comparison

TableColumn

<Customer, Number> ageColumn = new TableColumn<>("Age");ageColumn.setCellValueFactory(param -> param.getValue().ageProperty());ageColumn.setCellFactory(col -> new TableCell<Customer, Number>() { public void updateItem(Number age,

boolean empty) {

super.updateItem(age, empty); setText(null); setGraphic(null); if (!empty && age != null) { setText(age.toString()); setStyle("-fx-text-fill: " + (age.intValue() < 18 ? "red" : "black")); } }});JavaFX: Custom

TableCellSlide10
Code comparison

column

("Age", Customer::ageProperty).cellFormat { -> age text = "$age" style { textFill = if (age.toInt() < 18) RED else BLACK }}

TornadoFX: Custom

TableCellSlide11

TornadoFX Building BlocksSlide12
Type Safe Builders

Construct hierarchy of NodesCommon properties as paramsFunction block operates on the created Node

borderpane { top { toolbar { button("Refresh").action { onRefresh

()

} } }}Slide13
View

Container for the root Node

Contains UI logicOptionally delegates business logic to Controller or ViewModelViews are Singletons within a Scope - Fragments are notCan be embedded in other components or Views, or be the scene rootHot reloading during developmentclass MyView : View() {

override val

root = vbox { button("Click me").action { information("You clicked me!") } }}Slide14
Controller

Contains shared state and business logicInject into any other ComponentSingletons within the current Scope

class CustomerController : Controller() { val api: Rest by inject() fun listCustomers(): ObservableList<Customer> = api.get("customers"

).list().toModel()

}Slide15
Model

class Person {  val

firstNameProperty = SimpleStringProperty()  var firstName by firstNameProperty  val lastNameProperty = SimpleStringProperty()  var lastName by lastNameProperty}Slide16
ViewModel

Mediator between View and ModelRollback / CommitValidation / DecorationCan contain business logicItemViewModel

class PersonModel : ItemViewModel<Person>() {  val firstName = bind(Person::firstNameProperty)  val lastName = bind(Person::lastNameProperty)}Slide17
Scopes

Enables separation for JPro appsPerfect for MDIComponents are unique only within the scopeEasy grouping of UI and stateEnables testing Slide18

Code ExamplesSlide19
Forms

class

LoginForm : View("Login") { val user = UserModel() override val root = form { fieldset(title, labelPosition = VERTICAL) { field("Username"

) {

textfield(user.username).required() } field("Password") { passwordfield(user.password).required() } button("Log in") {

enableWhen(user

.valid)

action(

user

::

login)

}

}

}

}Slide20
FXML

Views can load the root Node from FXMLThe View becomes the Controller

class MyView : View() { val person: PersonModel by inject() override val root: ToolBar by fxml() val name: TextField

by fxid

() init { name.bind(person.name) } fun save() = person.save()}<ToolBar xmlns

="http://javafx.com/javafx"

xmlns:

fx

="http://javafx.com/

fxml

"

>

<

Label

text

="Name:"

/>

<

TextField

fx

:id

="name"

/>

<

Button

text

="Save"

onAction

="#save"

/>

</

ToolBar

>

class

MyView

: View() {

val

person

:

PersonModel

by

inject()

override val

root

=

toolbar

{

label

(

"Name:"

)

textfield

(

person

.

name

)

button

(

“Save"

).

action(

person

::

save)

}

}Slide21
Type Safe CSS

Inspired by type safe UI buildersExtremely refactorableCovers 95% of the JavaFX CSS supportVariables and even functionsColor.derive/ladderCSS hot reload

val mainColor = c("#bdbd22") val heading by cssclass() heading { textFill = mainColor

fontSize

= 20.px fontWeight = BOLD} button { padding = box(10.px, 20.px) borderColor += box(Color.DARKGRAY) }

label

(

"Hello TornadoFX"

).

addClass

(

heading

)Slide22
Charts

piechart

("Imported Fruits") { data("Grapefruit", 12.0) data("Oranges", 25.0) data("Plums", 10.0)

data(

"Pears", 22.0) data("Apples", 30.0)} barchart("Stock Monitoring, 2010", CategoryAxis(), NumberAxis()) { series("Portfolio 1") { data

("Jan",

23)

data

(

"Feb"

,

14

)

data

(

"Mar"

,

15

)

}

series(

"Portfolio 2"

) {

data

(

"Jan"

,

11

)

data

(

"Feb"

,

19

)

data

(

"Mar"

,

27

)

}

}

Slide23
OSGiSlide24

Turns TornadoFX into an RCP platform

Browser like navigation history (optional tabbed navigation)

Common action buttons connected to currently docked View

Optional drawers on all sides

Views can provide dynamic or static additions to the Workspace

WorkspaceSlide25
IntelliJ IDEA PluginGenerate code

Run configurationsRun Views directlyHot reload of Views and/or CSSIntentionsCustom editors (Ex Type Safe CSS color picker)Slide26
TornadoFX Community and Resources

GitHub tornadofx.io/githubSlack tornadofx.io/slackGuide tornadofx.io/guide

YouTube tornadofx.io/screencasts