Reputation: 2037
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
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):
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
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.
Jxxx
classes in Swing (except perhaps for custom painting). In your example you can use a JFrame
instead of extending itActionListener
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