First part
Learning objectives:
- Describe event-driven programming
- Conceive a simple application with a graphical user interface
- Implement a callback function
- Apply the concept of inheritance to conceive an application
- Conceive a class that implements an interface
Conponent vs Container
In order to program graphical interfaces, you will need to understand the concepts of component and containers. Each object in a GUI plays a precise part in the visual aspect of the application.
- The graphical components such as text fields (JTextField), the buttons (JButton), the list (JList) and labels (JLabel) and many others are used as base elements for your interface and must be place within a container.
- The containers such as the frame (JFrame), the dialog box (Jdialog) the panels (JPanel) and many others are used to contain the base elements in a specific layout (LayoutManager). We place the elements from left to right (flowLayout), in a grid format (GridLayout), by separating the containers in zones (BorderLayout) and others. A container can also contain sub-containers.
Consult Figure 0 below. It is a simple example that shows the base principle of a graphical interface. The panels, denoted by a blue rectangle are used as a container for the different base components. In red is the frame that is used to contain the panel. Identify the type of layout used for each of the 3 panels.

Exercise
Take the time to test the different possible layouts through this laboratory. You will need some practice to master graphical containers and components. Complete the following code to obtain the same window as Figure 1.
import javax.swing.*;
import java.awt.*;
public class MyFirstGUI{
public static void main(String[] args){
JFrame myFrame = new JFrame();
//set the title
myFrame.setTitle("My first Window");
//set the size to 500X300 pixels (width by heigth)
myFrame.setSize(500, 300);
//set the object to the middle of our screen
myFrame.setLocationRelativeTo(null);
//end program when user closes the window
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a panel
JPanel myPanel = new JPanel();
//add a label to the panel
myPanel.add(new Label("My first panel"));
//set panel background color
myPanel.setBackground(Color.green);
//add the panel to the frame
myFrame.add(myPanel, BorderLayout.NORTH);
//YOUR CODE HERE
//set the window to visible
myFrame.setVisible(true);
}
}

- The package java.swing contains the basic graphical swing classes:
- The graphical component classes (such as JButton, JTextField and JLabel)
- The graphical container classes (such as JFrame, Jpanel, Jdialog and JScrollPane)
- The graphical layout managers (such as FlowLayout, BorderLayout and GridLayout)
- The package java.awt contains the personalised class (such as Graphics, Color and Font). Event handling is also included in this package.
The packages
To make the classes more accessible to the compiling unit, you will need to use many import packages. Two packages will be very useful to program graphical user interfaces:
It is possible in Java to import a package and all classes that it contains by using the star “*” instead of the name of the desired class (see example above). It is however not a good practice because you would be importing classes that are not useful to your program, diminishing the efficiency of your program.
import javax.swing.*;
Event based programming
As mentioned before, java.awt.event takes charge of handling the events. For this lab, we will use:
- The event classes (such as ActionEvent, MouseEvent, KeyEvent and WindowEvent)
- Event listening interfaces (such as ActionListener, MouseListener, KeyListener and WindowListener)
Here are some key concepts for event handling in Java:
- All graphical components can be the source of an event. For example, a button creates an event when the user click on it, a text field creates an event when the user types “enter”
- All classes can handle one or many event type, they only need to:
- Implement the method(s) of an interface
- Add the instance to the list of event handler of the graphical component that generated the event
The objects handling the action event (such as a button click) have to implement the interface ActionListener.
- The event that is generated by a component is sent to all handlers registered with this component.
The source has a method addActionListener with a parameter of type ActionListener.
Since the handler implements the interface ActionListener, the source knows that the handler has the method actionPerformed(ActionEvent event).
Counter
Let’s re-examine the Counter example viewed in class. This example follows the concepts of Model-View-Controller
Model:
The model in this example is a Counter that increments an integer by 1, or resets it to 0 depending on what button is pressed. The class Counter implements this model using the necessary methods (increment, getValue, reset)
public class Counter {
private int value ;
public Counter () {
value = 0 ;
}
public void increment () {
value++;
}
public int getValue () {
return value ;
}
public void reset () {
value = 0 ;
}
public String toString () {
return "Counter : { value="+value+"}" ;
}
}
View:
We want to have multiple views for this Counter (2 views), but we want the program to interact with these views in the same manner. To do so, we create the interface View. This interface will act as a contract between the class that implements the interface View and the class that will interact with them. In this case, we can be certain that every class implementing the interface View will have the method void update().
public interface View {
void update () ;
}
There are two types of views that implements the interface View. The first one, TextView, is a textual representation of the counter which prints out the number of the counter. Note that it implements the method void update().
public class TextView implements View {
private Counter model ;
public TextView (Counter model) {
this.model = model ;
}
public void update() {
System.out.println(model.toString()) ;
}
}
The second view is the GraphicalView; this view is a Graphical User Interface (GUI) for the counter. This class extends Jframe, allowing it to have a graphical representation.
In the constructor of this view, we include as a parameter the model (Counter) as well as the controller (Controller) (see below). In the constructor we use " setLayout (new GridLayout(1 ,3)); ”, which divides the window in 1 row and 3 columns. This creates 3 positions where we can insert elements like buttons. To add buttons we follow these four steps:
- Declare the button (of type JButton)
- Initialize the button
- Add an ActionListener to the button
- Add the button to the frame (using the add function)
We can also use a JLabel to display text.
We will need some additional lines to setup the window properly:
- “setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ” means that closing the window will close the application
- “setSize(300, 100);” sets the size of the window (x axis, y axis)
- “setVisible(true); ” enables the window to be displayed
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GraphicalView extends JFrame implements View {
private JLabel input;
private Counter model;
public GraphicalView (Counter model, Controller controller) {
setLayout (new GridLayout(1 ,3));
this.model = model;
JButton button;
button = new JButton("Increment");
button.addActionListener(controller);
add(button);
JButton reset;
reset = new JButton ( "Reset" );
reset.addActionListener ( controller );
add(reset);
input = new JLabel ();
add(input);
//setup
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
//display the window
setVisible(true);
}
public void update () {
input.setText(Integer.toString(model.getValue())) ;
}
}
Controller:
We then have the Controller; this class handles the logic and communication of the application. This class has to implement ActionListener in order to be able to handle events thrown when the user clicks on a button.
This controller has an array of View, when the Controller is constructed; this array is populated with a GraphicalView and a TextView. The controller has a method update() that calls the method update() of every registered View.
The method ActionPerformed(ActionEvent e) is called each time that the GUI performs an action. This method verifies which action has been performed and reacts accordingly. It then updates the views.
import java.awt.event.*;
public class Controller implements ActionListener {
private Counter model;
private View[] views;
private int numberOfViews;
public Controller(){
views = new View[2];
numberOfViews = 0;
model = new Counter() ;
register(new GraphicalView(model, this));
register(new TextView(model));
update();
}
private void register(View view) {
views[numberOfViews] = view;
numberOfViews++;
}
private void update() {
for (int i = 0; i < numberOfViews; i++) {
views[i].update();
}
}
public void actionPerformed ( ActionEvent e ) {
if(e.getActionCommand().equals("Increment")) {
model.increment ();
} else {
model.reset();
}
update();
}
}
Application
Finally we have the class App that has a main method allowing the execution of the counter.
public class App {
public static void main(String[ ] args) {
Controller controller;
controller = new Controller();
}
}
1. Timer
For this exercise, you will need to make an application that has a Graphical User Interface that represents a timer.
Template files:
The Timer has 6 buttons, one that will increase and one that decreases hours, minutes and seconds respectively.
To create the Timer, we will base ourselves on the Counter example.
To adapt the code for the Counter to implement the Timer, we will need to change the model, the view, and the controller.
Model:
The previous model was the Counter; we need to replace this class with a new class Timer. The class Timer has:
- Three methods that increments the: hours, minutes and seconds respectively
- Three methods that decrements the: hours, minutes and seconds respectively
- Three methods that returns the: hours, minutes and seconds respectively
- We also need to respect the 24 hours cycle:
- The hours are between 0 and 23
- The minutes are between 0 and 59
- The seconds are between 0 and 59
View
You will need to modify the class GraphicalView so that it creates 6 buttons (to increment/decrements hours, minutes, and seconds) as well as a label (JLabel) that indicates the time. We will use a 2 (rows) by 3 (columns) grid to accommodate all these elements.
Controller
In the Controller, you will need to modify the method “public void actionPerformed ( ActionEvent e )” to accommodate the 6 actions launched by the 6 buttons of the GraphicalView and call the corresponding methods from Timer.
Here is an example of the result:

Figure 2 : Timer