GUI Programming In Java – PART THREE

We can get an event. We can paint graphics. But can we paint graphics when we get an event?

Every time you click the button, the circle will change colors. The program is structured as follows:

image 12 - GUI Programming In Java - PART THREE
image 13 - GUI Programming In Java - PART THREE
The color of the ball was supposed to be the same as the previous picture! We messed up while taking a screenshot!
image 14 - GUI Programming In Java - PART THREE
image 15 - GUI Programming In Java - PART THREE

jLvT2m44QoRCRidoHq zkMxOIunI sskamzXtKgpHX2 tK6c81o0g vExag1px6wYiiBBMmxOWuZvbkJ6BXeE8YE4objNXJh2WH c T5vk IDLRhHYgxK7zEOKpt11Wl3YhpYXgulQzYNUUXB4p - GUI Programming In Java - PART THREE

What Is A GUI Layout?

GUI layouts are covered in the following tutorial, but we’ll do a quick lesson here to get you started.

A frame has five regions that you can add to by default. You can only add one thing to each region of a frame. But do not worry!  That one thing could be a panel that holds three other things, including another panel that holds two more things, and so on. In fact, when we added a button to the frame, we were ‘cheating’.

frame.getContentPane().add(button);

This isn’t the way it’s supposed to be done (the one-arg add() method). The right approach is to use the two-args add() method.

frame.getContentPane().add(BorderLayout.CENTER, button);

The two-args add() method takes a region (using a constant) and the widget to add to that region as arguments.

uU2dq0BP LHahW hmkl448PWlPWZavuqF 62UygoBSTDGjwpabyPzNBv37djFaM0J0UOr1qzEqIUPcc3fA4pDJPv1OkO92ia6QjcYl8FoysyUR2NlnQZEw VCDhZveGdgum 1EErAcAilYLHS2gtyrT5e7 pk31U AaKhKZs4IlWybjtaeiwI 3z6OMhjw - GUI Programming In Java - PART THREE

In the following program, each time you click the button, the circle changes color.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
public class GUIDemo3 implements ActionListener {
 
    JFrame frame;
 
    public static void main (String[] args) {
        GUIDemo3 guiDemo3 = new GUIDemo3();
        guiDemo3.drawGUI();
    }
 
    public void drawGUI() {
 
        frame = new JFrame();
 
        JButton button = new JButton("Change color");
        button.addActionListener(this);//Add the listener (this) to the button.
 
        MyCustomDrawingPanel drawingPanel = new MyCustomDrawingPanel();
 
        // Add the two widgets (button and drawing panel) to
        // the two regions of the frame.
        frame.getContentPane().add(BorderLayout.SOUTH, button);
        frame.getContentPane().add(BorderLayout.CENTER, drawingPanel);
 
        frame.setSize(400,300);
        frame.setVisible(true);
       
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
    }
 
    public void actionPerformed(ActionEvent event) {
        /* When the user clicks, tell the frame
           to repaint() itself. That means
           paintComponent() is called on every
           widget in the frame! */
        frame.repaint();
    }
}
 
 
class MyCustomDrawingPanel extends JPanel {
    /* The drawing panel's paintComponent() method
    is called every time the user clicks.*/
   
    //the code in this method was discussed in RandomCircleDemo
    public void paintComponent(Graphics g) {
 
        g.fillRect(0,0,this.getWidth(), this.getHeight());
 
 
        int redColor = (int) (Math.random() * 256);
        int greenColor = (int) (Math.random() * 256);
        int blueColor = (int) (Math.random() * 256);
 
        Color randColor = new Color(redColor, greenColor, blueColor);
 
        g.setColor(randColor);
        g.fillOval(50,50,100,100);
 
    }
 
}

Let us try something a little more difficult. Let us put two buttons.

SqZZutZHfkWXz8CC59pQzIIT2e0MiP67oE9NQN9LlUFPswo5gfSC2st4MA9Rw90ZmDfcnVKYE1RO5UE6CYwWSPTilrYaO82DKHV3MKCgDVfJuCZr7W2mWPp3EsVW4vsuyk3s3iAlATRDTjIOOuioYn38Z8x djrkyQob1VCN2Hyvle Pm 3d KFBMLRQw - GUI Programming In Java - PART THREE

The south button will continue to function as it does now, calling repaint on the frame. The second button (which will be placed in the east region) will alter the text on a label. (A label is simply text on a screen). So now we need FOUR widgets.

And we need to get TWO events.

The UI will look something like this:

qnoSzwW2O2aJVkm0zblsM8kHsWSJITsiBB92AIt2EWIrRLe18Lsx109Y5NUNmD kVM2Dc6kFHRbwNx2jsU67Odhw1qtwdvVCwWKEmO4liGXirzmnclHKVcH8C8CZTIwMsL1a42zy2WVV AyWQnOmLpR REDf3VCRKfwMU0OOrGkv mF484QTwYdU1ylfYw - GUI Programming In Java - PART THREE

The GUI code is pretty simple. Just create A JLabel object and a JButton object and add them to the frame.

1.Creating the widgets
JButton labelButton = new JButton("Change Label");
 
JLabel label = new JLabel("A simple label!!");

2. Adding widgets to the frame
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);

The real problem arises when we attempt to get events from two different buttons. How do you get two events when you have only one actionPerformed() method? How do you get action events for two different buttons, when each button needs to do something different?

Approach 1

You might be tempted to implement two actionPerformed() methods.
    class CustomGUI implements ActionListener {
        /*
        some code goes here
        */
 
        public void actionPerformed(ActionEvent event) {
            frame.repaint();
        }
 
        public void actionPerformed(ActionEvent event) {
            label.setText("The text changed!!");
        }
    }
The issue is that you cannot do so. In a Java class, you cannot implement the same method twice. It will not compile. Even if you did, how would the event source know which of the two methods to invoke?

Approach 2

You may register the same listener with both buttons.
    class CustomGUI implements ActionListener {
        // declare a bunch of instance variables here
        public void drawGUI() {
            // build gui
            colorButton = new JButton();
            labelButton = new JButton();
            colorButton.addActionListener(this);
            labelButton.addActionListener(this);
            // more gui code here ...
        }
        public void actionPerformed(ActionEven event) {
            if (event.getSource() == colorButton) {
                frame.repaint();
            } else {
                label.setText("The text changed!!");
            }
        }
    }
This works, but it's not very OO in most cases. One event handler doing multiple things means you have a single method doing multiple things. You have to mess with everyone's event handler if you want to change how one source is handled. It is sometimes a good solution, but it usually hurts maintainability and extensibility.

Approach 3

You may create two separate ActionListener classes.
    class CustomGUI {
        JFrame frame;
        JLabel label;
        void gui() {
            // code to instantiate the two listeners and register one
            // with the color button and the other with the label button
        }
    } // close class
 
 
    class ColorButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            frame.repaint();
        }
    }
 
    class LabelButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            label.setText("The text changed!!");
        }
    }
These classes won't have access to the variables they need to act on, 'frame' and 'label'. You could fix it, but you'd have to give each of the listener classes a reference to the main GUI class, so that inside the actionPerformed() methods the listener could use the GUI class reference to access the variables of the GUI class. But that's breaking encapsulation, so we'd probably need to make getter methods for the gui widgets (getFrame(), getLabel(), etc.). And you'd probably need to add a constructor to the listener class so that you can pass the GUI reference to the listener at the time the listener is instantiated. And, well, it gets messier and more complicated.

There must be a better way! The solution to this problem is using inner classes. You can nest one class inside another. It’s simple. Just make sure the definition for the inner class is inside the outer class’s curly braces. The next tutorial will go over nested classes.

Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit

Check Our Ebook for This Online Course

Advanced topics are covered in this ebook with many practical examples.