0

I think that writing listeners in the same class is not OOP-way. So, I try to write listener in another file.

Code that works is:

class MyPanel extends JPanel{
 private String tString = "Test String";
 private JLabel tLabel;
 public MyPanel(){
    tLabel = new JLabel("Label");
    JButton tButton = new JButton("Click me");

    tButton.addActionListener(new ActionListener(){   
    public void ActionPerformed(ActionEvent e){
     tLabel.setText(tString);
    }
   });
}

But when I write listener in separated file:

public class MyListener implements ActionListener{
 copy code here
}

and change

tButton.addActionListener(new ActionListener(){

to

tButton.addActionListener(new MyListener());

it doesn't work. Of course i have tried different combinations.

For example, sending "this" to listener's constructor and calling methods from received object in listener's class.

Error:

MyListener: cannot find symbol "tLabel"
mKorbel
  • 109,525
  • 20
  • 134
  • 319

3 Answers3

1

Your MyListener class has to have a constructor. You pass "this" and whatever other parameters you need in the MyListener class constructor.

Here's an example from a project of mine.

package com.ggl.project.planner.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import com.ggl.project.planner.model.Planner;
import com.ggl.project.planner.model.Project;
import com.ggl.project.planner.view.CreateUpdateProjectDialog;
import com.ggl.project.planner.view.ProjectPlannerFrame;

public class CreateProjectActionListener implements ActionListener {

    protected Planner planner;

    protected Project project;

    protected ProjectPlannerFrame frame;

    public CreateProjectActionListener(ProjectPlannerFrame frame,
            Planner planner, Project project) {
        this.frame = frame;
        this.planner = planner;
        this.project = project;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        CreateUpdateProjectDialog dialog = 
                new CreateUpdateProjectDialog(frame, project, true);
        if (dialog.isOkPressed()) {
            planner.setProjectOpen(true);
        }
    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • Or you mean I have to pass every object from panel that I want to change? May be it works, I will try. But how to be, if i want to get the whole panel? For example to call her method? –  Sep 17 '12 at 15:10
  • @Danila: I pass (JPanel) "this" all the time. I usually call it "panel" in the listener. You would have methods in the JPanel class that the listener class can execute. For example, panel.setButton3Text(text); – Gilbert Le Blanc Sep 17 '12 at 15:30
1

Your MyListener class has no reference to the tLabel variable.

You can either set it through the constructor or pass the MyPanel reference to the MyListener and have a method in MyPanel that does the needed stuff on the JLabel and can be called from MyListener.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
  • Thank you. But how to pass MyPanel to MeListener? I tried "this", it doesn't work. –  Sep 17 '12 at 15:18
1

Thank you for editing your answer :)

It appears you're trying to access the tLabel variable from your new listener, but it's not accessible as it may be declared private. The same thing will probably also happen with tString. Try this:

public class MyListener implements ActionListener{

    private MyPanel myPanel;

    public MyListener(MyPanel myPanel) {
        this.myPanel = myPanel;
    }

    public void ActionPerformed(ActionEvent e) {
        myPanel.getTLabel().setText(myPanel.getTString());
    }
}

And add a getter for each of tString and tLabel to MyPanel:

public class MyPanel extends JPanel {

    // ...

    public String getTString() {
        return tString;
    }

    public JLabel getTLabel() {
        return tLabel;
    }
}

When you can't access a private field, generally you add a public "getter" which returns that field instead of changing the access of the field itself. Convention is that if, for example, the field is a String and is named myField, the getter is named getMyField. Like this, you can also add setters to set that variable. See this question for more on getters and setters.

Community
  • 1
  • 1
Brian
  • 17,079
  • 6
  • 43
  • 66
  • It's also worth noting that not having a setter is also acceptable. This is one way [immutable objects](http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) can be created. – Brian Sep 17 '12 at 15:17
  • Thank you! Just now I discovered, that in my listener's constructor param was JPanel but not MyPanel :D –  Sep 17 '12 at 15:31