Question

I currently have a class Frame that creates a frame, adds buttons and a label. I currently have the code for the action listener in my Frame class, and I need to move it so the action listeners are called from a anonymous class. Here is what I currently have.

 public static void main(String[] args)
 {
   Frame grid = new Frame();
    grid.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    grid.setVisible(true);
    grid.pack();
    grid.setTitle("Frame");
}

public class Frame extends JFrame
{
ImageIcon green = new ImageIcon("green.png");
JLabel label;
public JButton button1,button2;

public Frame()
{

    setLayout(new GridLayout(4,4));

  /**create buttons*/
    button1 = new JButton("");
    add(button1);
    button2 = new JButton("");
    add(button2);
    label = new JLabel(green);
    add(label);



/**Add action listener to buttons, I need these 2 liseners in a anonymous class */
button1.addActionListener(new ActionListener() 
{
        public void actionPerformed(ActionEvent arg0) 
        {
           button1.setText("X");                       
}

});
button2.addActionListener(new ActionListener() 
{
public void actionPerformed(ActionEvent arg0) 
{
           button2.setText("X");    

}

});

Can anyone show me how to move this actionlistener so that it is called from an anonymous class? Im under the assumption that I do this in main when I create my frame? Something like this maybe?

Frame grid = new Frame(){
       //Code might go here?
}

I am not sure, I am new with anonymous classes. Can anyone show me how to implement the action Listener in an anonymous class?

Was it helpful?

Solution 2

You probably mean something like that:

class Frame 
{
    private JButton button1;

    // Here it is:
    private ActionListener firstActionListener = new ActionListener()
    {
        public void actionPerformed(ActionEvent arg0) 
        {
            button1.setText("X");
        }
    };

    public Frame()
    {
        ....
        button1.addActionListener(firstActionListener);
    }
}

Although I wonder what you need this for. You might want to have a look at http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html

OTHER TIPS

You can't simply add a listener to component who neither supports the listener you are trying to attach or to a component to whom you don't have a reference to.

That is, JFrame doesn't support ActionListener and you don't have a reference to the buttons you want to add actions to.

I know you've made the buttons public, but to me, this is a bad idea, as you are exposing the components to outside modification. There's nothing stopping code from changing the state of the buttons, taking control away from the Frame class.

Instead, you should provide the ability for interested parties to register interest in knowing when the buttons are activated, for example...

public static class Frame extends JFrame {

    ImageIcon green = new ImageIcon("green.png");
    JLabel label;
    private JButton button1, button2;

    public Frame() {
        //...
    }

    public void addButton1ActionListener(ActionListener listener) {
        button1.addActionListener(listener);
    }

    public void addButton2ActionListener(ActionListener listener) {
        button2.addActionListener(listener);
    }

    public void removeButton1ActionListener(ActionListener listener) {
        button1.removeActionListener(listener);
    }

    public void removeButton2ActionListener(ActionListener listener) {
        button2.removeActionListener(listener);
    }

Then you would simply add your ActionListener to which ever button you want whenever you want to, for example...

public static void main(String[] args) {
    Frame grid = new Frame();
    grid.addButton1ActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Do stuff
        }
    });
    grid.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    grid.setVisible(true);
    grid.pack();
    grid.setTitle("Frame");
}

Now, this raises issues, because now you've provided access to the underlying button, which you might not want to.

Now, going beyond the question, I might suggest the use of some kind of model. This would be applied to Frame, which would allow it to modify its state as it sees fit, which would then provide event notification back to interested parties stating that some state or other has changed and that they should take appropriate action, such as updating the view.

This is best described by the MVC pattern

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top