Kotlin extensions for JavaFX app development
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
art
buildSrc
demo
gradle/wrapper
ktfx-commons
ktfx-coroutines
ktfx-layouts
ktfx-listeners
ktfx-thirdparty
ktfx
ruleset
testing
website
.gitignore
.travis.yml
CONTRIBUTING.md
LICENSE
README.md
build.gradle.kts
gradlew
gradlew.bat
settings.gradle.kts

README.md

ktfx

bintray download build license gitter

Kotlin extensions for JavaFX app development. Written in spirit of android-ktx and anko.

Consists of several parts:

  • ktfx-commons: full of helpers for common JavaFX application logic.
  • ktfx-layouts: dynamic JavaFX layout with Kotlin DSL.
  • ktfx-listeners: write common JavaFX listeners with Kotlin DSL.
  • ktfx-coroutines: utilities based on the kotlinx.coroutines library.

Download

All artifacts are hosted on jcenter. To download all of the main features, use:

dependencies {
    compile 'com.hendraanggrian.ktfx:ktfx:$version'
}

Or download separate libraries if only specific features are desired:

dependencies {
    compile 'com.hendraanggrian.ktfx:ktfx-commons:$version'
    compile 'com.hendraanggrian.ktfx:ktfx-layouts:$version'
    compile 'com.hendraanggrian.ktfx:ktfx-listeners:$version'
    compile 'com.hendraanggrian.ktfx:ktfx-coroutines:$version'
}

Commons extensions

Full of extensions for JavaFX, packaged accordingly. The main goal of core library is not to add any new feature to the existing JavaFX APIs. Below are preview of some of the packages.

Collections

// create unmodifiable observable collection
val emptyUnmodifiableList = emptyObservableList()
val unmodifiableList = observableListOf(1)

// create modifiable observable collection
val emptyModifiableList = mutableObservableListOf()
val modifiableList = mutableObservableListOf(1, 2, 3)

// convert existing
val list = myList.toObservableList() // or toMutableObservableList() for modifiable version

Bindings

// infix conditional binding
button.disableProperty().bind(firstName.textProperty().isEmpty or lastName.textProperty().isEmpty)

// operator binding for number properties
totalProperty.bind(qtyProperty * priceProperty)

// infix binding for number properties
loginButton.disableProperty().bind(passwordField.textProperty.length() less 4)

// custom binding
label.graphicProperty().bind(stringBindingOf(listView.selectionModel.selectedIndexProperty()) {
    "${listView.selectionModel.selectedIndex} selected"
})
imageView.imageProperty().bind(bindingOf(urlField.textProperty()) {
    Image(urlField.text)
})

Dialogs

// show an alert
alert("Here's an alert").show()

// show a confirmation alert and wait for input
confirmAlert("Are you sure?").showAndWait()

// custom init a text input dialog
inputDialog("Question #1") {
    contentText = "Why does the chicken cross the road?"
    editor.promptText = "Hint"
}.showAndWait()

// a choice dialog
choiceDialog("Pick an item", ImageView("/my/image.png"), items)
    .showAndWait()

// show a custom dialog
dialog<String>("Who's a little piggy?") {
    content = ...
    yesButton()
    noButton()
    customButton("What's a piggy?") {
        // explain what a piggy is
    }
    resultConverter {
        if(it == button1)  "Me" else null  
    }
}.showAndWait()

Layouts extensions

Generate JavaFX layouts, controls, shapes, and charts with Kotlin DSL. It's a direct replacement of FXML files.

gridPane {
    gaps = 8
    label("First name") row 0 col 0
    val firstName = textField() row 0 col 1
    label("Last name") row 1 col 0
    val lastName = textField() row 1 col 1
    button("Say hello") {
        setOnAction {
            infoAlert("Hello, ${firstName.text} ${lastName.text}!")
                .show()
        }
    } hpos RIGHT row 2 col 1
}

Layouts demo

Listeners extensions

Trade common JavaFX listener with Kotlin DSL. Currently includes string converters and table cells.

// string converter
val dateBox = ChoiceBox<Date>()
dateBox.converter {
    val dateFormat = SimpleDateFormat("dd/MM/yyyy")
    fromString {
        dateFormat.parse(it)
    }
    toString {
        dateFormat.format(it)
    }
}

// custom list cell
val personList = ListView<Person>()
personList.cellFactory {
    onUpdateItem { person, empty ->
        if (person != null && !empty) {
            graphic = Button("Do something")
        }
    }
}

Coroutines extensions

Based on the kotlinx.coroutines library, it allows invoking JavaFX EventHandler the coroutine way.

button.setOnAction {
    doSomethingInBackground()// might freeze UI
    celebrateCompletion()
}

button.onAction(CommonPool) {
    doSomethingInBackground() // non-blocking in common pool
    launch(FX) {
        celebrateCompletion()
    }
}

Third-party extensions

Some popular libraries are also supported. Though currently is limited.

dependencies {
    compile 'com.hendraanggrian.ktfx:ktfx-controlsfx:$version'
    compile 'com.hendraanggrian.ktfx:ktfx-jfoenix:$version'
    compile 'com.hendraanggrian.ktfx:ktfx-testfx:$version'
}

License

Copyright 2018 Hendra Anggrian

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.