G52GUI Graphical User Interfaces
Tutorials

These practicals aim to help you to get familiar with GUI implementation so that you can get on with the coursework.

This is not a programming module per se, so details of JavaFX, Eclipse, FXML and SceneBuilder will not be discussed in this module. The focus will be on GUI implementation using these tools.

Tutors
wil
Wil Ward
jinming
Jinming Duan
Practicals

The practicals will take place in the form of 5 labs, and the remainder of the practicals will be coursework help.

Lab OneSetup GUI development environment and create simple JavaFX application
Lab TwoCreate the basic Model and design the GUI (View)
Lab ThreeRoot your View and create the main Controller class
Lab FourCreate the Controller class to link the Model and View
Lab FiveManipulating the Model from the View
Lab Six(and onwards) Coursework help
Beyond the TutorialsAdditional functionality ideas for your coursework
Lab One

Getting up and running with JavaFX and SceneBuilder in Eclipse.

First, check the correct version of Java is installed. Open the command window (cmd.exe), or terminal, and run the command "java -version". For these tutorials, Java 8 (1.8.0) is required.

To download and install SceneBuilder, which will be used to design the View part of your user interface, click here. Accept the License Agreement and choose the version required for your operating system.

To use SceneBuilder with Eclipse, an additional plugin should be downloaded. The e(fx)clipse plug-in provides the tools to help with using JavaFX in Eclipse.

Installing e(fx)clipse must be done from within Eclipse. The steps to do so are as follows:

  1. Run Eclipse and, under the Help menu, select 'Install New Software...'
  2. Select 'Add...' and in the new 'Add Repository' window give the location as
    http://download.eclipse.org/efxclipse/updates-released/1.0.0/site
  3. Set the name to be "e(fx)clipse"
  4. In the following window, check only "e(fx)clipse - IDE" to install (if there are more than one choose the one that matches your version of Eclipse, e.g. Kepler or Luna)
  5. Confirm the installations, and click through the next windows. When requested, restart Eclipse.

The installation guide as listed above is also available with screenshots here.

Creating your JavaFX application.

This series of labs will be the development of a simple graphical user interface that shows a list of people that can be interacted with to display details of an individual person. Using the Model-View-Controller (MVC) architecture covered in lectures, the tutorials will describe how to split up the components and implement them.

First, a project needs to be setup. In Eclipse, in the Package Explorer, right click and select New > Java Project (or in the File > New > Java Project). Name your project, for example, "Tutorial", and uncheck Use default location. Select a location to save the project, double check the JRE used is JavaSE-1.8 and click 'Finish'.

The new project should now display in the Package Explorer. The next step is to create packages for the individual MVC components: right-click src and select New > Package. Create packages named "model", "view", with 'src' as their source folder (the Controller classes will to be placed in the default package due to aceess limitations in FXML).

These packages can now be used to develop the components of your GUI application.

Lab Two

Creating your Model

The model part of the application contains the element you want to represent. In this case it is a list of people, so first an object for a Person must be created. The following code describes a simple Person class. It simply contains the variables representing different properties of a person, i.e. name and address, and the corresponding getters and setters. This person class forms part of the model component of your MVC, and should be created in the "model" package.

This code is currently unavailable.

Designing your View

The first thing to create is the layout for the Person viewer. We will be using SceneBuilder for this, but before that, the file should be created. FXML is an XML based language for defining a user interface in JavaFX. Right click your "view" package and select New > Other... and from the browser that opens, select New FXML Document. Name it "PersonView", check that the root element is AnchorPane and click 'Finish'.

It is possible to create your UI using just the FXML file in Eclipse, but to simplify things greatly, in the Package Explorer, right click PersonView.fxml and click 'Open with SceneBuilder'.

Within SceneBuilder, you will see nothing in the central area. However, if you select the the AnchorPane in the Document Hierarchy (on the left), you will now see a crosshair in the centre of the window. This is your AnchorPane, but with size 0 x 0. Resize the AnchorPane either by dragging at the crosshair until the desired size is found, or by setting the 'Pref Width and Height' in the Layout tab on the right. The exact size is not important, but as a guideline, around 700 by 500.

Now the AnchorView is setup, you need to add components. FXML is hierarchical, so we should start at the bottom: first add a SplitPane (horizontal) by dragging it from the Library on the left (it is under the Containers tab) onto the AnchorPane. Right-click the SplitPane in the view (or in the Hierarchy) and select 'Fit to Parent'.

Drag the divider in the SplitPane so that it is approximately in the centre. Note in the Hierarchy that there are two AnchorPanes in the SplitPane. These correspond the left and right parts of the pane. Now click the left side and drag in a TableView control from the Library. Now, selecting the TableView, set the 'Anchor Pane Constraints' in the Layout tab so that all values are equal to 10. Under Properties:TableView, choose 'Column Resize Policy' to be 'constrained-resize'. This will ensure that the columns will always take up available space. Rename them 'First Name' and 'Last Name' respectively by double clicking on the headers.

For the right side of the View, you will need to put a first put a Label at the top. This can be found in the Library and dragged into position. In the Properties tab, set the text to 'Details', and adjust the font as desired.

Now drag a GridPane into the right AnchorPane. The size can now be anchored using the Layout tab. Set the parameters so that the GridPane is constrained from the sides by 5, and from the top by 50. Now, add more rows so that there are 5 in total. This can be done by selecting an existing row number (it will turn yellow), right-clicking and selecting 'Add Row Below' (or 'Above').

Drag Labels into each of the grid cells and name rename those in the left column with the properties of a Person, as shown in the above screenshot.

Create three Buttons now, and place them at the bottom right of the AnchorPane. Select all three (using Shift + click) and right-click selecting Wrap in > HBox. Change the spacing of the HBox to 10 and position in the bottom right using the 'Anchor Pane Constraints'. Now rename each button to 'New...', 'Edit...' and 'Delete'.

To check how your UI View looks, choose from the top menu Preview > Show Preview in Window. You should see something like the following:

Now that the PersonView FXML file is created, save and close SceneBuilder. In Eclipse you will now see that the PersonView.fxml file has been updated with the new elements created using SceneBuilder.

Lab Three

Creating a Root layout for the View

Before you can use the PersonViewer interface with your JavaFX application, another view must be created to wrap it. This is called a root layout, and will be used to contain and interface.

In the "view" package, create another New FXML Document, but this time set the root element to be a BorderPane. Name it "RootLayout" and open in SceneBuilder (by right-clicking the file in the Package Explorer).

As with the PersonView, the SceneBuilder viewer is blank. Click BorderPane in the hierarchy and set the 'Pref Width' and 'Pref Height' to be 700 and 500 respectively from the Layout tab.

From the 'Controls' tab of the Library, choose MenuBar and drag it to the top of your BorderPane. Save and close SceneBuilder.

Setting up your JavaFX Main Class

Now that the basic model and view are generated, a main class is needed to initialise the application. To create a main class for a JavaFX application, a different type of file should be used. Right click the "src" folder, and select New > Other... to open up the browser. Search for the JavaFX Main Class wizard and click 'Next'. Name the file "MainApp", check that it belongs to the "default" package, and click 'Finish'.

The new MainApp is a class that extends the JavaFX Application class, and contains a static main() method consisting of the line launch(args);. Calling launch() initialises the JavaFX application, and calls the start() method. start() takes as input a Stage representing the main container of the application, e.g. the GUI window. On this Stage, the application is built as a Scene. This is represented by the different layouts created with FXML. The following code sets the RootLayout and PersonView as your Scene in the Stage that forms your application:

This code is currently unavailable.

You should now be able to build and run your project. The resulting application will display a new window containing your PersonView with the MenuBar created in the RootLayout.

Lab Four

Creating the PersonView Controller

Now that you have your Model and View, it is time to create the Controller that connects the two. First, you should create a new Java class in the default package (where you created MainApp) named PersonViewController.

This class will contain instant variables that will correspond to different components in your PersonView FXML file. As such, they will need to be appended with the @FXML annotation before each variable declaration. Note: this is only a requirement for private declarations. The corresponding FXML Library objects will need to be imported.

This code is currently unavailable.

The initialize() method is called automatically after an FXML file is loaded (or at least, an FXML file with PersonViewController set as the Controller). Notice that there is a MainApp object, and a call is made to its function getPersonData(). Do not worry about this for now – we will address this in the final step of this lab.

Linking View and Controller

You now need to direct your PersonView to the controller. Right click and open PersonView in SceneBuilder. In SceneBuilder, on the left side there is a tab called 'Controller'. You can now link the View and Controller by setting the 'Controller class' to be "PersonViewController".

Once the controller is set up, the 'fx:id' for each component needs to be setup. Remembering the variable declared in PersonViewController, you can go about this using the 'Identity' section of the 'Code' tab on the right of SceneBuilder. Click on the TableView in the viewer, or in the Hierarchy tab, and set the fx:id as "personTable". For each of the TableColumns, assign the respective fx:id "firstNameColumn" and "lastNameColumn".

In addition to the list of Persons, you will want to display their information. Now, for each of the Labels, on the right column of the GridPane, set the fx:ids (in this order), "firstNameLabel"; "lastNameLabel"; "streetLabel"; "postalCodeLabel"; and "cityLabel". You may get an error flash at the top of SceneBuilder saying "No injectable field found in FXML Controller class for the id 'firstNameLabel'", etc. This will not be a problem in running your application. SceneBuilder cannot find the variable names in PersonViewController because they are set to private. The @FXML annotation that you included will solve this during compilation.

Save PersonView.fxml, and return to Eclipse. To update the project with the changes made in SceneBuilder, you will need to refresh the project. Do this by right-clicking your project in the Package Explorer, and clicking 'Refresh'.

Filling your View

This label will look at filling the PersonView to display a list of people (i.e. Persons). First, you need to add a constructor to your MainApp class, so that when an instance of the class is created, an example set of Persons is created. This will also introduce the ObservableList JavaFX collection. Insert the following imports into your MainApp file.

This code is currently unavailable.

An ObservableList, and indeed other JavaFX Observable Collections, are extensions on their corresponding java.util data structures. The Observable class and its subclasses, e.g. ObservableList, etc., are designed to handle the threads used in JavaFX. What's important, however, is simply that an Observable collection is a version of its counterpart java.util collection, but with an added event listener. That is, a method called when some event (such as a button click) occurs. This is an essential requirement for keeping the data structures in sync with the View, so you will need to use Observable collections in your JavaFX application.

Insert the following code into your MainApp class. It contains the code for instantiating your ObservableList of Persons, the corresponding getter and a constructor to initially fill the list.

This code is currently unavailable.

You must now make sure your MainApp has access to the controller. This is taken directly from PersonView. In the method showPersonView() (in MainApp.java), add the following two lines at the end of the try block, after personView has been loaded and set in the centre of rootLayout

This code is currently unavailable.

If you compile and run your application now, you should now see your list of people in the table column, as in the above screenshot.

Lab Five

Listening to your View

You will notice that, so far, you can only display a list of people that have been created directly in the MainApp constructor. As well as this, there is also no real way to interact with the View, such as to display a selected Person's details in the right pane.

When running, you can select a Person in the left TableView, and they will be highlighted but nothing else will happen. You can add an event listener to this TableView from the controller. At the initialize() method in your PersonViewController class, add the following lines of code (make sure you put the entire command inside the initialize() method!):

This code is currently unavailable.

The previous command adds a ChangeListener to your personTable, which when triggered will run a function that identifies the new selection and executes the method showPersonDetails() with that selection. You will need to import the ChangeListener and ObservableValue.

import javafx.beans.value.*;

You'll now need to actually create the showPersonDetails() method, it will take in a Person class and display the respective details. This should be added to your PersonViewController. The method will fill the right hand Labels with the values from the Person object, using setText(). If the input is null, the Labels are set to empty strings. This is important, as the method will be called with a null input if deselection of a Person in the View occurs (Ctrl + click).

This code is currently unavailable.

Deleting a Person

Viewing the pre-defined set of Persons is all well and good, but being able to add, edit or delete a Person would be a useful feature in the PersonView.

Deleting a Person is by far the simplest thing to do. The user will simply have to select a Person and click "Delete". The program should then delete that Person and remove it from the personTable.

First, you will need to create the method that is called when the "Delete" button is pressed. You will need to deal with the method being called even for an empty table, however this is as easy as checking the selected index is 0 or above. Add the following method to your PersonViewController.

This code is currently unavailable.

The "Delete" button now needs to be linked to its handle method. Open PersonView in SceneBuilder, and select the "Delete" Button. On the right hand side in the 'Code:Button' tab, set 'On Action' to your method name: "handleDeletePerson". This means that now, when the Button is pressed, your method will be executed. Save in SceneBuilder and refresh you Project.

Adding and Editing

Your GUI application will now have the capability to delete the preset Persons. You also will want to enable the user to manually add/change a Person's details, so we will create a new user interface to do this. Create a new FXML Document in your "view" package (New > Other...). Set the name as "PersonEdit" and 'Root Element' as a AnchorPane. Open the new PersonEdit.fxml in SceneBuilder.

Try to create the view shown in the screenshot on the right. You will need to add a GridPane onto the initial AnchorPane. The right column uses Labels, and the left TextFields (you will find these in the 'Controls' tab of the Library). The "OK" and "Cancel" Buttons are wrapped in an HBox. Save and return to Eclipse.

Now to create the Controller for your PersonEdit View. In the default package, create a new Java Class named "PersonEditController". This will need to contain the appropriate imports for the JavaFX components in your FXML file, as well as the model. Variables for the names of each of your TextFields are needed, as well as a Stage (for showing the View), and a Person currently being edited. The Controller should handle setting the Stage, as well as appropriate setters: setting the Person will automatically fill the text fields with its details. Button clicks should also be handled, i.e. handleOk(), which will update the Person with the details in the TextFields, and handleCancel(), which should close the PersonEditview with no changes to the Model.

This code is currently unavailable.

You will now need to link your View to your Controller. In SceneBuilder, set the 'Controller' of your PersonEdit to be "PersonEditController". Now, for each of the TextFields, set their fx:id to the corresponding @FXML variable in your PersonEditController, e.g. firstNameField. Finally, for the two Buttons, set their 'On Action' values to be handleOk and handleCancel respectively.

The Controller and View should now be linked correctly. You will now want to actually be able to open your PersonEdit view. To do this, you'll need to declare an additional Stage with the PersonEdit as its Scene. This will be "owned" by your main application Stage (the one that displays your PersonView). The following method should be added to MainApp. It will load your PersonEdit fxml file and create a Stage to display it. The input requires a Person, and this is the Person the user will be editing.

This code is currently unavailable.

The command editStage.showAndWait() causes the PersonEdit view to be displayed, and pauses the runtime in the MainApp until the view is closed by the user. The method will check if the "OK" Button was clicked, and returns that as a boolean. Returning false implies "Cancel" was pressed.

The final step now is to link this to the PersonView "New..." and "Edit..." Buttons. You'll need to create handle methods handleNewPerson() and handleEditPerson() in your PersonViewController class. We can use the PersonEdit to create a new Person by simply giving it a blank Person to edit. Remember to check that the "OK" Button is clicked, otherwise you will add an blank Person to your TableView!

This code is currently unavailable.
This code is currently unavailable.

Your completed Model-View-Controller application

Now you have added all the functionality, you will be able to view, edit and delete your model. If you compile and run the JavaFX application, you should have your completed PersonView. The project containing the full tutorial can be downloaded from here.

These tutorials cover the basic functionality and JavaFX tools required to complete your coursework, however you may wish to add additional features not covered. You can look at various sources online, and use the JavaFX references to complete your assignment and bring your coursework idea into existence. The section below provides some potential ideas for extending your complexity of your program.

Beyond the Tutorials

Using CSS to style your View

A brief introduction and tutorial for styling your GUI with CSS and JavaFX can be found here.

Last updated 2014 | School of Computer Science