Universidad Carlos III de Madrid

Ingeniería de Telecomunicación

Enero-Mayo 2010 / January-May 2010

Graphical User Interfaces

Lab Section1.  Session 2 (lab): Graphical User Interfaces

Exercise Section1.1. Hello World using Swing

Run the following application:

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class HelloWorld extends JFrame {

    public HelloWorld() {
        super("HelloWorld");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(new JLabel("Hello World!"));
        setMinimumSize(new Dimension(200,100));
        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() {
                    HelloWorld gui = new HelloWorld();
                }
            });
    }
}

Section 1

Answer the following questions:

  1. Which class does HelloWorld extend from? Find this class in the Java API. Indicate the complete inheritance chain, from HelloWorld to Object.
  2. Which method is invoked when super("HelloWorld") is executed? Find this method documentation in the Java API.
  3. What does the method setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) do? Answer this question using the Java API.
  4. What is the line setVisible(true) used for? Find its documentation in the Java API. Why is not setVisible among the JFrame methods?
Solutions
  1. HelloWorld extends from JFrame. The complete inheritance chain can be observed in JFrame API: java.lang.Object, java.awt.Component, java.awt.Container, java.awt.Window, java.awt.Frame, javax.swing.JFrame, HelloWorld.
  2. When super("HelloWorld") is executed, the constructor of JFrame is invoked. This constructor receives an only parameter, which type is String.
  3. The method setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) configures the window behavior when the user requests to close the window. In the case of using JFrame.EXIT_ON_CLOSE as parameter, it indicates the application to exit when the user closes the window. You can check this information in the Java API.
  4. When a window is created, it is not visible in the user's desktop. When setVisible is invoked with true as parameter, the window becomes visible. This method is not explicitly among the JFrame ones, but the class inherits it from java.awt.Window, and therefore, it can use it.

Section 2

In the previous application, the class HelloWorld extends from JFrame. Another alternative would be not to extend from this class, but to create internally a JFrame object and use it to construct the window. Code a new class called HelloWorld2. This new class must behave as HelloWorld, without extending from JFrame.

Solutions
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class HelloWorld2 {

    public HelloWorld2() {
        JFrame frame = new JFrame("HelloWorld");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JLabel("Hello World!"));
        frame.setMinimumSize(new Dimension(200,100));
        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() {
                    HelloWorld2 gui = new HelloWorld2();
                }
            });
    }
}

Exercise Section1.2. Calculator using Swing

Code an application that shows a calculator similar to the one in the following image:

For now, there is no need for the calculator to react to user's actions (e.g. pressing a key). It just has to always show 0 as result.

In order to obtain a similar aspect to the one showed in the image, you can establish a BorderLayout in the window upper level. Then, you can add:

  • A label showing the string "0" in the upper part of the window (BorderLayout.NORTH). This label will emulate the calculator screen. Align the label to the right using the appropriate constructor.
  • A panel, managed by a GridLayout, in the center of the window (BorderLayout.CENTER). This panel will show one calculator key in each cell.

Solutions

import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class Calculator extends JFrame {

    public Calculator() {
        super("Calculator");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout());
        JLabel display = new JLabel("0", SwingConstants.RIGHT);
        JPanel buttonsPanel = new JPanel(new GridLayout(6, 3));
        buttonsPanel.add(new JButton("AC"));
        buttonsPanel.add(new JButton("+"));
        buttonsPanel.add(new JButton("-"));
        buttonsPanel.add(new JButton("C"));
        buttonsPanel.add(new JButton("*"));
        buttonsPanel.add(new JButton("/"));
        buttonsPanel.add(new JButton("7"));
        buttonsPanel.add(new JButton("8"));
        buttonsPanel.add(new JButton("9"));
        buttonsPanel.add(new JButton("4"));
        buttonsPanel.add(new JButton("5"));
        buttonsPanel.add(new JButton("6"));
        buttonsPanel.add(new JButton("1"));
        buttonsPanel.add(new JButton("2"));
        buttonsPanel.add(new JButton("3"));
        buttonsPanel.add(new JButton("."));
        buttonsPanel.add(new JButton("0"));
        buttonsPanel.add(new JButton("="));
        getContentPane().add(display, BorderLayout.NORTH);
        getContentPane().add(buttonsPanel, BorderLayout.CENTER);
        pack();
        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() {
                    Calculator gui = new Calculator();
                }
            });
    }
}

Exercise Section1.3. Drawing Area

Besides using the existing components provided by Swing, a graphical application may also draw lines, circles, text and other figures directly over objects of JPanel class. Consider the next example consisting of two classes. The first one extends from JPanel and serves as the drawing canvas:

import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;


public class Canvas extends JPanel {
    private Dimension preferredSize;

    public Canvas(Dimension preferredSize) {
        this.preferredSize = preferredSize;
    }

    public Dimension getPreferredSize() {
        return preferredSize;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension size = getSize();
        int width = (int) size.getWidth();
        int height = (int) size.getHeight();
        g.drawLine(0, 0, width - 1, height - 1);
        g.drawLine(width - 1, 0, 0, height - 1);
    }
}

The second class is a window containing an instance of the previous class:

import java.awt.Dimension;

import javax.swing.JFrame;

public class CanvasApplication extends JFrame {

    public CanvasApplication() {
        super("Canvas");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(new Canvas(new Dimension(640, 480)));
        pack();
        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() {
                    CanvasApplication gui = new CanvasApplication();
                }
            });
    }
}

Run the application and observe carefully how it works. What happens if you change the window size?

Swing invokes the method paintComponent from Canvas every time the application needs to be redrawn (e.g., when the window size changes). In this method, the object received as parameter, which belongs to Graphics class, is used to draw the lines defining the panel diagonals. Take a closer look at this class API. Notice that you can also draw arcs, ovals, polygons, text, images, etc. It is also possible to establish the drawing color or the text font.

Modify the method paintComponent so that it draws what you want. Use, at least, polygons and circles (only their outline, or adding their filling too), text and different colors. This way you can practice the use of Graphics class. In order to learn how to draw each of the figures mentioned above, check the class API.

Solutions

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;


public class Canvas2 extends JPanel {
    private Dimension preferredSize;

    public Canvas2(Dimension preferredSize) {
        this.preferredSize = preferredSize;
    }

    public Dimension getPreferredSize() {
        return preferredSize;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension size = getSize();
        int width = (int) size.getWidth();
        int height = (int) size.getHeight();
        g.drawLine(0, 0, width - 1, height - 1);
        g.drawLine(width - 1, 0, 0, height - 1);
        g.setColor(Color.BLUE);
        g.fillOval(width / 2 - 32, height / 2 - 32, 64, 64);
        g.setColor(Color.RED);
        g.drawString("This is Swing!", 60, 60);
        g.drawPolygon(new int[]{50,  100,  40, 110, 75},
                      new int[]{200,  200,  260, 260, 290}, 5);
    }
}
import java.awt.Dimension;

import javax.swing.JFrame;

public class CanvasApplication2 extends JFrame {

    public CanvasApplication2() {
        super("Canvas");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(new Canvas2(new Dimension(640, 480)));
        pack();
        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() {
                    CanvasApplication2 gui = new CanvasApplication2();
                }
            });
    }
}