In this hands-on session, the objective is to get acquainted with the Swing java library.
The session heavily relies on the official Swing tutorial. The objective of this page is to give you a low friction path through the main concepts in Swing. Concepts are discussed in depth in the documentation and you will also find a wealth of examples that illustrate all concepts.
Main Window (Frame)
You are given the following code as a starting point. Run it on you machine and try to answer the questions below.
import java.awt.*;
import javax.swing.*;
public class FrameDemo {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("Greetings Swinger");
emptyLabel.setPreferredSize(new Dimension(175, 100));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
// make window's dimension fit its content
frame.pack();
// Display the window.
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Questions:
- Change the title of the window to something more catchy.
- What is the purpose of the
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
line? Verify you assumption by removing the line. Is the program still running after closing the window? - which line decides the size of the
JLabel
? What happens if you:- remove it?
- make it smaller than the text?
- Which line is used to determine the window's size? What happens if you remove it?
A JFrame
is a top-level container. Each application has at least one top-level containers in which other components are placed.
JLabel
The label is the most basic component in Swing. It allows displaying short text or images. So far you have used to display a raw text, but it supports several features to control how a text should be displayed, either through the JLabel
API or through HTML.
Exercises:
- Make the label's text centered
- Make the text of the label red
Having several components in a frame
Each container is associated to layouts that determines how its component are organized in two dimensions:
In the case of the JFrame
, the default layout is a BorderLayout
Exercise:
-
In which part of the frame's
BorderLayout
is ourJLabel
displayed? -
Add a new button in the bottom part of the frame (
JButton button = new JButton("Click Me!")
) -
What happens if you add more than on component to the part of the layout?
Laying Out Components: grouping with JPanel
Now that we are Swing power-users, we wish to build a real application: a counter. In order to get founding for the start-up, you need an MVP, that:
- displays the current value of the counter at the center,
- provides two buttons at the bottom to respectively decrease and increase the counter.
You are now facing a major technical problem: it is impossible to add two components at the bottom of the frame... Luckily an expensive consulting company (McKinsa), gives you the solution:
Indeed, you can only place a single component at the bottom of a BorderLayout. However, when facing this situation you can group your buttons in a JPanel container. This will essentially create a new component containing you two buttons. You can then place it where you want in the frame.
- JPanel
- Flow Layout (default for JPanel)
- BoxLayout (another common layout)
Exercise:
Place two buttons "-"
and "+"
at the bottom of your counter app.
Buttons and events
So far, we have displayed buttons but nothing was happening when clicking on them. This is made possible by the Oberserver design pattern implemented by the buttons.
Each button has a list of ActionListener
. Each time an action (e.g. a click) happens on this button, the actionPerformed(...)
method of each listener is called; Some context on the action is provided in ActionEvent
parameter.
public void actionPerformed(ActionEvent e) {
...// code that reacts to the action...
}
Exercise: For each button, create an ActionListener
that prints MINUS/PLUS to the standard output when the button is clicked.
Custom components
One of the (very few) great things about Object-Oriented Programming is that you can specialize an existing class for your purpose. In GUI programming, this comes extremely handy as it allows providing custom components very easily.
Exercise:
-
Complete the following subclass of
JLabel
so that it displays the current value of thecounter
in its text field anytime the counter is updated with thesetCounter()
method. Note that, like anyJLabel
, it has asetText(...)
method to update the text of -
Replace the
JLabel
you previously used in the counter application by your newCounterComponent
-
Update your actions listener to call the
decrease()
/increase()
methods of the component.
static class CounterComponent extends JLabel {
private int counter = 0;
public CounterComponent() {
// set style, dimensions, ...
}
void setCounter(int newValue) {
...
}
void increase() {
...
}
void decrease() {
...
}
}
Text fields
NASA has a great use case for your counter to serve has the central component for the count-down before launch.
Problem is, in the current version, the launch officer has to click 10 times on the +
button before starting the countdown.
Exercise: Make the counter editable by using a JTextField
instead of a JLabel
as the base class for CounterComponent
. Make sure that the count number can still be updated with the buttons.
Exercise: Add a new Start Countdown
button that would:
- decrement the counter every second (remember the lab on
Thread
s andTimer
s) - Display a dialog when the countdown reaches 0 (be creative with its content)