I have a JButton in my program, defined as follows (more or less)
public class MyTester{
public static void main(String[] args)
{
int counter = 0;
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
startButton.doSomething()
counter++;
}
}
);
}
}
I want to be able to count the number of times that the button is clicked. Problem is, I can't declare a counter and then 开发者_运维百科increment it after the call to .doSomething(), because the variable has to be final for me to reference it in the inner class.
Is there a way to do this, other than creating my own wrapper class with its own .increment() method?
Depending on threading situation, you can move the variable to the enclosing class. But this can go very wrong if you invoke foo()
several times, since that will use the same counter.
public class MyClass {
// Notice the placement outside the main()
private static int counter = 0;
public static void main(String[] args) {
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
startButton.doSomething()
//do some more stuff
counter++;
}
}
);
}
}
You can move your counter from outside the ActionListener
to inside, making it a member of the listener.
public class MyTester {
public static void main(String[] args) {
final JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
int counter; // you make one per listener
public void actionPerformed(ActionEvent e) {
startButton.doSomething();
counter++;
}
});
}
}
As suggested by @akf, the counter can be a member of a nested class, from which members of the enclosing instance are visible. This example implements ActionListener
to extend AbstractAction
.
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** @see http://stackoverflow.com/questions/4290117 */
public class ClickCount extends JPanel {
private JButton button = new JButton(new ClickHandler("Click"));
private JLabel label = new JLabel("0");
public ClickCount() {
this.add(button);
this.add(label);
}
private class ClickHandler extends AbstractAction {
int counter;
public ClickHandler(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
label.setText(String.valueOf(++counter));
}
}
private void display() {
JFrame f = new JFrame("ClickCount");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ClickCount().display();
}
});
}
}
精彩评论