Experimenting with Java enums, emojis, and ComboBox in JavaFX
Learn how to use Java enums and emojis with a JavaFX ComboBox.
Upgrading my JavaFX ToDoList application
In the second iteration of my Java TodoListApplication
, I used the JavaFX DatePicker
and TableView
components. I also introduced a Java record named ToDoItem
to see how I could use records in a JavaFX application.
I said in my previous blog that I was going to make my ToDoList persistent. Iβm still planning on doing this (next blog!), but I realized I wanted to add one more piece of information first to my ToDoItem
before making it persistent.
Adding a ToDoCategory enum
I wanted to add a category to my ToDoItem
record to keep track of to do items by category. So I created a ToDoCategory
enum with categories that match things that I do on a regular basis.
public enum ToDoCategory
{
EXERCISE("π΄"),
WORK("π"),
RELAX("π§"),
TV("πΊ"),
READ("π"),
EVENT("π"),
CODE("π»"),
COFFEE("βοΈ"),
EAT("π½"),
SHOP("π"),
SLEEP("π΄");
private String emoji;
ToDoCategory(String emoji)
{
this.emoji = emoji;
}
public String getEmoji()
{
return this.emoji;
}
}
I added a getter for the emoji String
named getEmoji
. This will be important later.
Updating my ToDoItem
record
It was a fairly straightforward change to update my ToDoItem
record with the ToDoCategory
. The important bit is that while the ToDoItem
holds onto a reference to a ToDoCategory
, it will return the emoji
from the category in the getCategory
method.
public record ToDoItem(String name, ToDoCategory category, LocalDate date)
{
public String getCategory()
{
return this.category.getEmoji();
}
public String getName()
{
return this.name;
}
public String getDate()
{
return this.date.toString();
}
}
Adding a ComboBox
The next step I wanted to add a ComboBox
to my todolist-view.fxml
. I placed the todoCategory
ComboBox
between the todoItem
TextField
and todoDate
DatePicker
.
<HBox id="HBox1" alignment="CENTER_LEFT" spacing="5.0">
<Label text="Item: " />
<TextField fx:id="todoItem" />
<Label text="Category: " />
<ComboBox fx:id="todoCategory" />
<Label text="Date: " />
<DatePicker fx:id="todoDate" />
</HBox>
I bound the ComboBox
to a variable named todoCategory
and added it to my TodoListController
.
@FXML
public ComboBox<ToDoCategory> todoCategory;
Then I needed to write some code to populate the values in the ComboxBox
with all of the ToDoCategory
enum values. So I updated the initialize
method of the TodoListController
.
@FXML
protected void initialize()
{
this.todoList.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
MutableList<ToDoItem> items = Lists.mutable.empty();
ObservableList<ToDoItem> list = FXCollections.observableList(items);
this.todoList.setItems(list);
ObservableList<ToDoCategory> categories =
FXCollections.observableList(Lists.mutable.with(ToDoCategory.values()));
this.todoCategory.setItems(categories);
}
I wrapped the array returned from the values
method of the ToDoCategory
enum with an Eclipse Collections MutableList
, and then wrapped that in an ObservableList
using the FXCollections
utility class.
The text that is displayed in the ComboBox
is the return value for the toString
implementation for each of the enums, which will be the enum text itself. This works as I had hoped.
Updating the onAddButtonClick code
When the add button is clicked, I now need to construct the ToDoItem
instance with all three UI component values. This was straightforward to add the todoCategory
ComboBox
selected value.
@FXML
protected void onAddButtonClick()
{
ToDoItem item = new ToDoItem(
this.todoItem.getText(),
this.todoCategory.getValue(),
this.todoDate.getValue());
this.todoList.getItems().add(item);
}
Adding a category column to the TableView
Finally, I wanted to add the category column to the TableView
. I decided it would be cool to display the emoji value for the ToDoCategory
enum here.
<TableView fx:id="todoList">
<columns>
<TableColumn text="Name" minWidth="75.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="name" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Category" minWidth="50.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="category" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Date" minWidth="50.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="date" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
I added the category column between the name and date columns and made it sortable.
My updated JavaFX TodoListApplication View
This is what my TodoListApplication looks like running now.
You may note that I have a category for reading, but not for writing. I may change this, but decided for this iteration, I would just categorize writing this blog under RELAX. Writing is a form of mental relaxation for me. I keep very focused, sort my thoughts, and write them down relieving my brain of having to hold onto too much information. Writing is my mental equivalent of Yoga.
My todolist-view.fxml & TodoListController Source
Out of convenience, I have put most of my code including the ToDoItem
and ToDoCategory
types in the TodoController
class. I may change this in future iterations. The TodoListApplicaton
code hasnβt changed since my last blog, so please refer to it there if you want.
todolist-view.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="example.todolist.TodoListController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
<HBox id="HBox1" alignment="CENTER_LEFT" spacing="5.0">
<Label text="Item: " />
<TextField fx:id="todoItem" />
<Label text="Category: " />
<ComboBox fx:id="todoCategory" />
<Label text="Date: " />
<DatePicker fx:id="todoDate" />
</HBox>
<TableView fx:id="todoList">
<columns>
<TableColumn text="Name" minWidth="75.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="name" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Category" minWidth="50.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="category" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Date" minWidth="50.0" sortable="true">
<cellValueFactory>
<PropertyValueFactory property="date" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
<HBox id="HBox2" alignment="CENTER" spacing="5.0">
<Button text="Add" onAction="#onAddButtonClick" alignment="BOTTOM_LEFT" />
<Button text="Remove" onAction="#onRemoveButtonClick" alignment="BOTTOM_RIGHT" />
</HBox>
</VBox>
TodoListController
package example.todolist;
import java.time.LocalDate;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.MutableList;
public class TodoListController
{
@FXML
private TextField todoItem;
@FXML
public ComboBox<ToDoCategory> todoCategory;
@FXML
private DatePicker todoDate;
@FXML
private TableView<ToDoItem> todoList;
@FXML
protected void initialize()
{
this.todoList.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
MutableList<ToDoItem> items = Lists.mutable.empty();
ObservableList<ToDoItem> list = FXCollections.observableList(items);
this.todoList.setItems(list);
ObservableList<ToDoCategory> categories =
FXCollections.observableList(
Lists.mutable.with(ToDoCategory.values()));
this.todoCategory.setItems(categories);
}
@FXML
protected void onAddButtonClick()
{
ToDoItem item = new ToDoItem(
this.todoItem.getText(),
this.todoCategory.getValue(),
this.todoDate.getValue());
this.todoList.getItems().add(item);
}
@FXML
protected void onRemoveButtonClick()
{
int indexToRemove = this.todoList.getSelectionModel()
.getSelectedIndex();
this.todoList.getItems().remove(indexToRemove);
}
public record ToDoItem(String name, ToDoCategory category, LocalDate date)
{
public String getCategory()
{
return this.category.getEmoji();
}
public String getName()
{
return this.name;
}
public String getDate()
{
return this.date.toString();
}
}
public enum ToDoCategory
{
EXERCISE("π΄"),
WORK("π"),
RELAX("π§"),
TV("πΊ"),
READ("π"),
EVENT("π"),
CODE("π»"),
COFFEE("βοΈ"),
EAT("π½"),
SHOP("π"),
SLEEP("π΄");
private String emoji;
ToDoCategory(String emoji)
{
this.emoji = emoji;
}
public String getEmoji()
{
return this.emoji;
}
}
}
Next Steps
My next step will be to make my ToDo List persistent. Iβve used enough JavaFX components now and want to experience more of the lifecycle of a JavaFX application. I hope you enjoyed this brief detour of using Java enum, emojis and ComboBox
in JavaFX. π
Thank you for reading!
I am the creator of and a Committer for the Eclipse Collections OSS project which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.