I'm aware that there are existing questions about JButton
s, but I haven't found anything that's asking exactly what I'm trying to figure out.
I inherited a Java project that has a horrible structure; my job is essentially to go through and fix it. The project includes a GUI, which is where this question becomes relevant.
In the state that I inherited it, the GUI's buttons simply didn't work correctly. I don't have an exact way to describe it, but essentially the previous programmer neglected event-driven programming, and set up a bunch of busy-wait threads waiting for things to happen. It did not work.
In the course of trying to get the buttons to trigger the correct state change in the GUI, I completely reworked the buttons into this form:
JButton button = new JButton(new AbstractAction("A button") {
@Override
public void actionPerformed(ActionEvent ae) {
doStuff();
}
});
As far as I can tell, this works correctly; doStuff()
is called, which handles the GUI's state transitions. This form is the result of struggling with different methods suggested at various places; this is the only one that I was able to get to work.
My specific question at this point is, firstly, is there a problem with using an AbstractAction
in this form to listen for a button click, and secondly, is there a better way to do this? Most everyone uses button.addActionListener()
, which is what I couldn't get to work correctly. If it's at all relevant, there are multiple buttons on some GUI states.
I'm using Java 7 for this. However, it wouldn't be a huge deal to switch to Java 8.
1 Answer 1
What you are already doing is a nice way of defining both the text for the button and the action for it at the same time.
As you're able to use Java 8, I would really recommend that you start using Java 8.
You might actually even want to consider migrating to JavaFX (that would probably require even more work though, but it could be a nice user interface upgrade).
One option, when using Java 8, is to do this:
JButton button = new JButton("A button");
button.addActionListener(this::doStuff);
private void doStuff(ActionEvent event) {
...
}
Or:
JButton button = new JButton("A button");
button.addActionListener(e -> this.doStuff());
private void doStuff() {
...
}
A different approach would be to do this:
JButton createButton(String text, Runnable action) {
return new JButton(new AbstractAction(text) {
@Override
public void actionPerformed(ActionEvent ae) {
action.run();
}
});
}
And then:
JButton button = createButton("A button", this::doStuff);
JButton button = createButton("Another button", () -> this.doStuff());
-
\$\begingroup\$ Thanks for the fantastic answer! I need to verify that Java 8 is available on the target machines, but if it's not, I'll definitely get it installed. I hadn't thought of using lambda expressions, but they seem perfect here. \$\endgroup\$millinon– millinon2014年12月16日 04:38:16 +00:00Commented Dec 16, 2014 at 4:38
addActionListener
not to work, especially since your job seems to be fixing such bugs causing such flaky behavior. \$\endgroup\$