Skip to content

How to Handle Events in a multiple Class Java Swing Project?

For example I have two Java Classes:

public class MainFrame extend JFrame implements ActionListener{
    public SouthPanel SPanel = new SouthPanel();
    public int foo = 0;
    MainFrame() {
        
        //MainFrame config
         this.add(SPanel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        
    }

}


public class SouthPanel extend Panel {
   public JButton openNewWindow = new JButton();
   public JLabel label = new Label();
   SouthPanel() {
      //button and label config
      //adding component
      }
}

What can i do to make a feature that when i click a button from the SouthPanel and foo in MainFrame will change.

Answer

So, in most UI frameworks, you have a concept of an “observer pattern”, this is way for interested parties to register interest been notified when something happens to the object.

Swing makes use of “listeners” to facilitate this basic concept. You’re not stuck to using the listeners that Swing defines and you can create your own, for example…

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import java.util.EventObject;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                SouthPane southPane = new SouthPane();
                southPane.addSourceListener(new SouthListener() {
                    @Override
                    public void somethingDidHappen(SouthEvent evt) {
                        System.out.println("Something important this way did happen");
                    }
                });
                frame.add(southPane);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    // So you can attach additional properties about the event itself
    public class SouthEvent extends EventObject {

        public SouthEvent(SouthPane source) {
            super(source);
        }

    }

    // Describes what actions the SouthPane might generate
    public interface SouthListener extends EventListener {
        public void somethingDidHappen(SouthEvent evt);
    }

    public class SouthPane extends JPanel {

        public SouthPane() {
            JButton btn = new JButton("Click me");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    fireSomethingDidHappen();
                }
            });
            add(btn);
        }

        public void addSourceListener(SouthListener listener) {
            listenerList.add(SouthListener.class, listener);
        }

        public void removeSouthListener(SouthListener listener) {
            listenerList.remove(SouthListener.class, listener);
        }

        protected void fireSomethingDidHappen() {
            SouthListener[] listeners = listenerList.getListeners(SouthListener.class);
            if (listeners.length == 0) {
                return;
            }
            SouthEvent event = new SouthEvent(this);
            for (SouthListener listener : listeners) {
                listener.somethingDidHappen(event);
            }
        }

    }
}

This example is deliberately long winded, as you don’t “always” need to create an event object, but it is a good way to pass back information to the observer, as it might not actually have a direct reference to object it’s monitoring.