Kotlin JavaFX - ListView - Fill From Array


JavaFX is now the number one GUI toolkit for creating rich graphical java applications.

It allows us create graphical user interfaces programmatically using predefined classes in an object oriented manner.

In this tutorial we look at how to populate a JavaFX ListView from an array. We then show a JavaFX dialog when an item is selected from the JavaFX ListView.

We are Building a Vibrant YouTube Community

We have a fast rising YouTube Channel of friends. So far we've accumulated almost 3 million agreggate views and more than 10,000 subscribers as of the time of writing this. Here's the Channel: ProgrammingWizards TV.

Please go ahead subscribe(free obviously) as well. If you have a question or a comment you can post there instead of in this site.People are suggesting us tutorials to do there so you can too.

You can check our YouTube Video version of this tutorial right here:

What is Kotlin?

Kotlin is a programming language targeting the Java platform. Kotlin is concise, safe, pragmatic, and focused on interoperability with Java code.

Kotlin is usble almost everywhere Java is used today - for server-side development, Android apps, and much more.

Kotlin like Java is a statically typed programming language. This implies the type of every expression in a program is known at compile time, and the compiler can validate that the methods and fields you’re trying to access exist on the objects you’re using.

However, Kotlin doesn’t require you to specify the type of every variable explicitly in your source code. In many cases, the type of a variable can automatically be determined from the context, allowing you to omit the type declaration.

Defining Packages in Kotlin

Normally classes are organized in packages in Java. This applies to Kotlin as well.

Package specification should be at the top of the source file:

package info.camposha
import java.util.*
class Starter{
    ...
}

However, be aware that it's not required to match directories and packages: source files can be placed arbitrarily in the file system.

Defining Functions in Kotlin

Roughly speaking, functions in Kotlin are the equivalent of methods in java.

Functions can take input parameters and can return values. Here's such a function:

fun sum(a: Int, b: Int): Int {
    return a + b
}

This can be condensed into a single line given that it has an expression body and we can infer the retur types:

fun sum(a: Int, b: Int) = a + b

However, if functions do not return any meaningful value:

fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}

Kotlin Arrays

Arrays in Kotlin are represented by the Array class, that has get and set functions (that turn into [] by operator overloading conventions), and size property, along with a few other useful member functions:

Here's Kotlin Array's signature:

class Array<T> private constructor() {
    val size: Int
    operator fun get(index: Int): T
    operator fun set(index: Int, value: T): Unit
    operator fun iterator(): Iterator<T>
    ...
}

Creating an Array

Creating an array in Kotlin is as easy as it can get. All you have to do is use the arrayOf() function amd pass you array elements:

arrayOf("Horse Head", "Black Widow", "Ghost Head", "Cat's Eye", "Elephant's Trunk", "Helix", "Rosette", "Snake", "Bernad 68", "Ant", "Orion", "Butterfly", "Eagle", "Own", "Ring", "Pelican", "Cone", "Flame", "Witch Head", "Bumerang")

Let's write a full Kotlin example with JavaFX. This example involves filling our JavaFX ListView with an array of data in Kotlin. Then when an item is clicked we show the item in a messagebox.

Neb.kt

Here's our code:

package info.camposha

import javafx.application.Application
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.Group
import javafx.scene.Scene
import javafx.scene.control.Alert
import javafx.scene.control.Label
import javafx.scene.control.ListView
import javafx.scene.layout.VBox
import javafx.scene.text.Font
import javafx.stage.Stage
import java.lang.Exception
import java.util.*

class Neb : Application() {

    internal var mListView = object
    /*
    Construct JavaFX UI
     */
    @Throws(Exception::class)
    override fun start(stage: Stage) {
        val scene = Scene(Group())
        stage.title = "Kotlin JavaFX : ListView - Fill From Array"
        stage.width = 550.0
        stage.height = 550.0

        val titleLabel = Label("Kotlin Array of Nebulas")
        titleLabel.font = Font("Lucida", 20.0)

        val listview = ListView<Any>()
        mListView=listview

        populateData()
        handleItemClicks()

        val vbox = VBox()
        vbox.spacing = 5.0
        vbox.padding = Insets(10.0, 0.0, 0.0, 10.0)
        vbox.children.addAll(titleLabel, listview)
        vbox.alignment = Pos.CENTER

        val group = scene.root as Group
        group.children.add(vbox)
        group.layoutX = 100.0

        stage.scene = scene
        stage.show()
    }

    /*
    Populate ListView with ArrayList data
     */
    private fun populateData()
    {
        val nebulae = arrayOf("Horse Head", "Black Widow", "Ghost Head", "Cat's Eye", "Elephant's Trunk", "Helix", "Rosette", "Snake", "Bernad 68", "Ant", "Orion", "Butterfly", "Eagle", "Own", "Ring", "Pelican", "Cone", "Flame", "Witch Head", "Bumerang")
        val lv:ListView<Any> = mListView as ListView<Any>
        for (nebular in nebulae) {
            lv.items.add(nebular)
        }

    }
    /*
     Handle ListView itemClicks
     */
    private fun handleItemClicks() {
        val lv:ListView<Any> = mListView as ListView<Any>
        lv.setOnMouseClicked({
            val selectedItem = lv.selectionModel.selectedItem.toString()
            val d = Alert(Alert.AlertType.INFORMATION, selectedItem)
            d.show()
        })
    }
    /*
    Launch application
     */
    fun go(args:Array<String>)
    {
        Application.launch(*args)
    }
    companion object {
        /*
         Main method
       */
        @JvmStatic fun main(args: Array<String>) {
            Neb().go(args)
        }
    }
}

Explanation

First we specify our imports using the import statement. Mostof our imports are from javafx.scene package.

Create JavaFX Application

We will create our class and make it derive from javafx.application.Application package:

class Neb : Application(){..}

We will have an instance field initialized to an object:

internal var mListView = object

Override the start() method

We will then override the start() method defined in the javafx.application.Application package:

override fun start(stage: Stage)

That function is taking in a javafx.stage.Stage object. This will be the primary stage of the application.

Our start() method will be throwing ajava.lang.Exception so we decorate it with the @Throws(Exception::class) attribute.

First we will instantiate the javafx.scene.Scene object, passing it a javafx.scene.Group object:

val scene = Scene(Group())

Set JavaFX stage properties

Then set the title,width and height properties of the stage object:

stage.title = "Kotlin JavaFX : ListView - Fill From Array"
stage.width = 550.0
stage.height = 550.0

Create JavaFX Label and set custom Font

We will instantiate the javafx.scene.control.Label object, set its text property via the constructor and set the Label Font:

    val titleLabel = Label("Kotlin Array of Nebulas")
    titleLabel.font = Font("Lucida", 20.0)

Instantiate JavaFX ListView

Then instantiate our javafx.scene.control.ListView and assign it to the instance field we had defined earlier on:

val listview = ListView<Any>()
mListView=listview

We will then invoke the populateData() and handleItemClicks() methods:

populateData()
handleItemClicks()

Create VBox and set its properties

Next we will instantiate a javafx.scene.layout.VBox, set its spacing, padding, children and alignment:

        val vbox = VBox()
        vbox.spacing = 5.0
        vbox.padding = Insets(10.0, 0.0, 0.0, 10.0)
        vbox.children.addAll(titleLabel, listview)
        vbox.alignment = Pos.CENTER

Add VBox to Group

Then obtain the javafx.scene.layout.Group reference, add it our vbox and set the layoutX property:

        val group = scene.root as Group
        group.children.add(vbox)
        group.layoutX = 100.0

Set JavaFX Scene to primary Stage and show Stage

Then set the stage to our scene and show the stage via the show() method:

        stage.scene = scene
        stage.show()

Create a Kotlin Array and populate it with data

Next we will create an array in kotlin using the arrayOf() method:

val nebulae = arrayOf("Horse Head", "Black Widow", "Ghost Head", "Cat's Eye", "Elephant's Trunk", "Helix", "Rosette", "Snake", "Bernad 68", "Ant", "Orion", "Butterfly", "Eagle", "Own", "Ring", "Pelican", "Cone", "Flame", "Witch Head", "Bumerang")

Convert our Object to ListView

Then cast our mListView object to a ListView using the as operator:

        val lv:ListView<Any> = mListView as ListView<Any>

Loop though Kotlin Array and add items to JavaFX ListView

Then loop through the array filling and fill our javafx ListView with items from the kotlin array:

        for (nebular in nebulae) {
            lv.items.add(nebular)
        }

JavaFX ListView Selected ItemClicks handling

We want to handle the itemClicks for the ListView. So we will us the setOnMouseClicked() event handler:

        val lv:ListView<Any> = mListView as ListView<Any>
        lv.setOnMouseClicked(..)

Then get the selected item from the selectionModel and casting it to a string:

val selectedItem = lv.selectionModel.selectedItem.toString()

Create a JavaFX Alert and show selected item

In the javafx.scene.control package is defined an Alert class that we can use to show alert dialogs or modals.

So we instantiate the Alert class, passing it the selected item:

val d = Alert(Alert.AlertType.INFORMATION, selectedItem)

and call show to show the javafx dialog:

d.show()

Launch the JavaFX application

We will then launch our JavaFX application:

fun go(args:Array<String>)
    {
        Application.launch(*args)
    }
    companion object {
        /*
         Main method
       */
        @JvmStatic fun main(args: Array<String>) {
            Neb().go(args)
        }
    }

Best Regards.

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think

Dear readers drop us your comments below. We are building a community of students and learners. Start by dropping us your suggestions below. What tutorials do you want us to do for example? Where can we improve? What are some awesome resources out there? Do you have any code you want to share with us?
By the way that example or snippet you have lying in your computer can really help beginner programmers. We can share it here with other students.

Previous Post Next Post