Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Agile forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

separate Event Listener class

 
Lisa Bergeron
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need to take the following code and instead of having the ActionListener implemented by the JFrame class, I have to create a separate class. I think I know how to call the separate ActionListener class from the JFrame class, however, creating the separate ActionListener class is posing a challenge. Anyone??
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class JFrame5 extends JFrame implements ActionListener {
Container c = this.getContentPane();
Toolkit kit = Toolkit.getDefaultToolkit();
ImageIcon img1 = new ImageIcon("c:\\Javagrl\\One.jpg");
ImageIcon img2 = new ImageIcon("c:\\Javagrl\\Two.JPG");
ImageIcon img3 = new ImageIcon("c:\\Javagrl\\Three.JPG");
JPanel top = new JPanel();
JPanel bottom = new JPanel();
JPanel center = new JPanel();
JPanel jp1 = new JPanel();
JPanel jp2 = new JPanel();
JPanel jp3 = new JPanel();
JLabel lab1 = new JLabel(img1);
JLabel lab2 = new JLabel(img2);
JLabel lab3 = new JLabel(img3);
JButton ImageOne = new JButton("Image One");
JButton ImageTwo = new JButton("Image Two");
JButton ImageThree = new JButton("Image Three");
CardLayout card = new CardLayout();
FlowLayout flow = new FlowLayout();
// remember that a frame has a default layout of border
public JFrame5() {
super();
}
public JFrame5(String title) {
super(title);
}
public void createJFrame() {
this.setDefaultCloseOperation(3);
this.setSize(500, 500);
this.show();
}
public void makePanels() {
bottom.setLayout(flow);
flow.setHgap(10);
top.add(ImageOne);
top.add(ImageTwo);
top.add(ImageThree);
ImageOne.addActionListener(this);
ImageTwo.addActionListener(this);
ImageThree.addActionListener(this);
center.setLayout(card);
jp1.add(lab1);
jp2.add(lab2);
jp3.add(lab3);
center.add(jp1, "firstPanel");
center.add(jp2, "secondPanel");
center.add(jp3, "thirdPanel");
card.show(center, "firstPanel");
c.add("South", bottom);
c.add("Center", center);
c.add("North", top);
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == ImageOne) {
card.first(center);
}
if (source == ImageTwo) {
card.next(center);
}
if (source == ImageThree) {
card.last(center);
}
}
}
 
chi Lin
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
define one more class like,
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e){
...
...
}
}
in the JFrame5, one line like
addActionListener(new MyActionListener() );
[ December 01, 2003: Message edited by: chi Lin ]
 
Lisa Bergeron
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks,
I do know HOW to construct a basic class. I guess what I can't figure out is how to call the event listener from theJFrame class. ALso, the event listener will need to DO something (Action event). If this method is in the separate Event Listener class...that class does not know what a card is, what an image is, etc....not sure if I am making myself clear, I am very fuzzy on this.
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == ImageOne) {
card.first(center);
}
if (source == ImageTwo) {
card.next(center);
}
if (source == ImageThree) {
card.last(center);
}
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's common to make listeners as anonymous inner classes. Then they have access to the outer class's variables and methods. (If inner & outer classes are not familiar, ask about that next!) Here's an example I could put my hands on quickly, taken from the initialization code in a JFrame:

addWindowListner is a standard JFrame thing. By saying "new someInterfaceName()" we indicate we want to define a class that implements an interface and create an instance all at once. Then in the next set of braces we define the class with just the one method. The inner class as access to the outer class methods, so it can call exitForm on the frame. Neat, huh?
I like to avoid putting any logic in these listeners, but just have them forward the event to another method. Then you could call the same method from a menu listener, a button listener, a window listener, etc.
Hope that gets you going!
 
Lisa Bergeron
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks.
I have been tasked with making this code work three ways.
A separate outer Listener Class, as an inner class, and also to make the componeent (in this case the JFrame) a listener itself.
I have completed the inner class and using the JFrame as a listener. (ie: MyJFrame extends JFrame implements ActionListener). I am still stuck on creating this separate Listener class...the below code won't work because my action listener does not know what a card is or what an ImageIcon is, etc....I just know this has to be simple but I have a serious block!
public class MyListener extends ActionListener{
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == ImageOne) {
card.first(center);
}
if (source == ImageTwo) {
card.next(center);
}
if (source == ImageThree) {
card.last(center);
}
}
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, you've already been where I went. Sorry about that. You are right, your external listener won't have access to the methods and variables in the JFrame without some work. One option: When you create the external listener, give it a reference to the frame:

This is probably not precisely right, but you get the idea that the listener has to go through the parent frame to get references to anything it wants to work on.
This has a lot of coupling. That is, the listener knows too much about the frame. And it violates the Don't Confuse Your Dog rule.
We could decouple these a bit by leaving all the logic on the frame and just letting the frame know something has happened. Maybe the actionEvent would look like:

The method theUserClicked(source) looks an awful lot like the original actionEvent in your example, but you've satisfied the assignment without too much new coupling. Hope that helps!
[ December 05, 2003: Message edited by: Stan James ]
 
Lisa Bergeron
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you so much - that was awesome and even entertaining - the way Java should be! I understood right away. This is what ended up in my Listener Class: I could only get it to work by also creating an instance of the JFrame here. If I take that away, it won't work.
public class MyActionListener implements ActionListener {
public MyActionListener(JFrame6 parent) {
myParent = parent;
}
JFrame6 myParent = new JFrame6();
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == myParent.ImageOne) {
myParent.card.first(myParent.center);
}
if (source == myParent.ImageTwo) {
myParent.card.next(myParent.center);
}
if (source == myParent.ImageThree) {
myParent.card.last(myParent.center);
}
}
}
I also did this in my JFrame Class:
ImageOne.addActionListener(new MyActionListener(this));
ImageTwo.addActionListener(new MyActionListener(this));
ImageThree.addActionListener(new MyActionListener(this));
It worked first try! Thanks again - class is tomorrow - maybe I can have a life tonight
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic