HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Adding action listener to Swing JButton

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
listeneraddingactionswingjbutton

Problem

I'm aware that there are existing questions about JButtons, 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.

Solution

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());

Code Snippets

JButton button = new JButton("A button");
button.addActionListener(this::doStuff);

private void doStuff(ActionEvent event) {
    ...
}
JButton button = new JButton("A button");
button.addActionListener(e -> this.doStuff());

private void doStuff() {
    ...
}
JButton createButton(String text, Runnable action) {
    return new JButton(new AbstractAction(text) {
        @Override
        public void actionPerformed(ActionEvent ae) {
             action.run();
        }
    });
}
JButton button = createButton("A button", this::doStuff);
JButton button = createButton("Another button", () -> this.doStuff());

Context

StackExchange Code Review Q#69510, answer score: 5

Revisions (0)

No revisions yet.