VanSpoof
VanSpoof

Reputation: 17

Using multiple JButtons with the same label in Java

I have two buttons in my project that both have a "+" label. When the actionPerformed() method is called, it calls a specific method based on the label. How can I distiguish between two JButtons with the same label? Is there a better way to do this then how I've done it?

This is the definition of the buttons:

JButton keypadPlus1 = new JButton(" + ");
JButton keypadMinus1 = new JButton(" - ");
JButton keypadPlus2 = new JButton("+");
JButton keypadMinus2 = new JButton("-");

Adding the ActionListeners for the buttons:

keypadPlus1.addActionListener(backEnd);
keypadPlus2.addActionListener(backEnd);
keypadMinus1.addActionListener(backEnd);
keypadMinus2.addActionListener(backEnd);

The actionPerformed @Override in the backEnd:

public void actionPerformed (ActionEvent event) {
        String command = event.getActionCommand();
        if (command.equals("+")) {
            calcLifePoints(command);
        }
        if (command.equals("-")) {
            calcLifePoints(command);
        }
        if (command.equals(" + ")) {
            calcLifePoints(command);
        }
        if (command.equals(" - ")) {
            calcLifePoints(command);
        }

    }

Upvotes: 0

Views: 731

Answers (3)

Kiran Rajam
Kiran Rajam

Reputation: 186

Instead of this,

public void actionPerformed (ActionEvent event) {
        String command = event.getActionCommand();
        if (command.equals("+")) {
            calcLifePoints(command);
        }
        if (command.equals("-")) {
            calcLifePoints(command);
        }
        if (command.equals(" + ")) {
            calcLifePoints(command);
        }
        if (command.equals(" - ")) {
            calcLifePoints(command);
        }

    }

Use like this,

public void actionPerformed (ActionEvent event) {
        Object command = event.getSource();
        if (command.equals(keypadPlus1)) {
            calcLifePoints(event.getActionCommand());
        }
        if (command.equals(keypadMinus1)) {
            calcLifePoints(event.getActionCommand());
        }
        if (command.equals(keypadPlus2)) {
            calcLifePoints(event.getActionCommand());
        }
        if (command.equals(keypadMinus2)) {
            calcLifePoints(event.getActionCommand());
        }

    }

Upvotes: 0

Vince
Vince

Reputation: 15146

You shouldn't have a single listener handle the behavior for different responsibilities. If the two + buttons do not do the same thing, give the buttons separate listeners.

This will allow your code to be a lot more cohesive. By reducing your listeners to 1 responsibility each, you'll be able to re-use those responsibilities. It also make testing easier, allowing you to test each behavior in complete isolation.

Although if you must, ActionEvent#getSource() returns which ever component triggered the event. Doing a reference comparison will allow you to determine which object triggered the event.


The best way to handle this would to separate the responsibilities your current listener has into separate classes:

class FirstListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {

    }
}

Lets assume FirstListener represents your first + button behavior. If that behavior requires any external objects (such as a field in a different class), simply pass it through the constructor:

class FirstListener implements ActionListener {
    private Object dependency;

    public FirstListener(Object dependency) {
         this.dependency = dependency;
    }

    //actionPerformed declaration
}

You can do the same for the other buttons (for example, the second + button).

If you feel this is a bit excessive, feel free to use lambda expressions to declare the listeners:

//Java 8+
button.addActionListener(event -> {

});

This doesn't give you the same modularity as the previous example, as the behavior is no longer separated from the actual class: you will be forced to change the implementation to change the behavior, rather than using dependency inversion to simply pass a different object which also implements ActionListener.

Upvotes: 2

MadProgrammer
MadProgrammer

Reputation: 347194

You could...

Use ActionEvent#getSource

You could...

Set the actionCommand property of each button to something unique and use ActionEvent#getActionCommand

You could...

Use separate listeners, either anonymously or as inner or outer classes depending on your needs

You could...

Make use of the Action API, which would allow you to define a common/abstract Action which defined the common properties (like the + text) and then extend this to make unique actions for each button

See How to Use Actions for more details

You could...

Use JButton#putClientProperty to set some unique flag on each button and cast the ActionEvent to a JComponent and use getClientProperty to retrieve the flag ... but given the previous suggestions, I'm not sure why you'd bother

Upvotes: 2

Related Questions