JavaNewbie_M107
JavaNewbie_M107

Reputation: 2037

Can a component itself be used as a listener?

I have tried using this code in Java, where I used a JFrame as it's own ActionListener. Now, it is theoretically possible, because in Java, a class can both implement a number of interfaces and extend another class.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;

/*
 * This is an example of the strangeness of the syntax of Java. In this example, I am using the JFrame itself as the listener for its component, namely a JButton which, on clicking, ends the program. 
 * Warning : This is just an example, and I would never recommend this syntax, for I do not know the full consequences yet.
 */

@SuppressWarnings("serial") public class ListenerTest extends JFrame implements ActionListener{

    private final JPanel contentPane;
    private final JLabel message;
    private final JButton button;

    /**
     * Launch the application.
     */
    public static void main(String[] args){
        EventQueue.invokeLater(new Runnable(){
            @Override public void run(){
                try{
                    ListenerTest frame = new ListenerTest();
                    frame.setVisible(true);
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public ListenerTest(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 200, 150);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));

        message = new JLabel("Hello World");
        message.setFont(new Font("Times New Roman", Font.PLAIN, 16));
        message.setHorizontalAlignment(SwingConstants.CENTER);
        contentPane.add(message, BorderLayout.CENTER);

        button = new JButton("Click Me!");
        button.addActionListener(this);
        contentPane.add(button, BorderLayout.SOUTH);
    }

    @Override public void actionPerformed(ActionEvent arg0){
        JOptionPane.showMessageDialog(null, "Well, I listened for myself!");
        System.exit(0);
    }

}

My question is : Is there any problem in using a component as its own listener?

Upvotes: 2

Views: 677

Answers (2)

David Kroukamp
David Kroukamp

Reputation: 36423

Why would you want to implement the ActionListener on the class if it is used for a single button only?

The side effects of this are:

  • adds to the fact other classes and components have access to this listener

  • more checking will be needed to identify which component is firing the listener (as I see many reuse listeners for other components using if checks for which fired the listener).

  • Not really good practice to implement a Listener on the class unless class will be used as a listener.

Proper solution IMO:

Use anonymous inner class listeners:

ActionListener al=new ActionListener() {
    @Override
     public void ActionPerformed(ActionEvent ae) {
     }
};

now you can add this to your single button via addActionListener.

the reason I come to the above conclusion of not wanting to implement the listener on the class is in Swing You should not extend the JFrame class unnecessarily.

notes (not as relevant to particular problem):

  • As my own coding preferecnce do not use EventQueue rather SwingUtilities.invokeXXX though as @Robin said who stated the docs: As of 1.3 this method is just a cover for java.awt.EventQueue.invokeLater()

Upvotes: 4

Robin
Robin

Reputation: 36611

Does it work ... yes.

That being said. I can give you hundred of examples of bad coding practices, and this would be one of them.

  • There is almost never a need to extend the Jxxx classes in Swing (except perhaps for custom painting). In your example you can use a JFrame instead of extending it
  • Having a class which implements the ActionListener interface suggests to users of your API/code that it can be used as an ActionListener. However, your class is not designed as an ActionListener. The fact that it is one is an implementation detail which can better be hidden. So use an ActionListener (anonymous class, inner class, ... ) instead of implementing it directly (or even better, use an Action)

And no, implementing the ActionListener interface directly has nothing to do with I saw that the GUI took a long time to load

And as a side-note. Better to use JFrame#pack() then the call to setBounds.

Upvotes: 5

Related Questions