ada dudu ada dudu - 5 months ago 17
Java Question

Adding more mouselisteners to 1 JButton?

Is it possible to add more than 1 mouselistener to a JButton? You know when I click on the button it should change color and text, and do something (e.g system.out.println), and when I click it again it should go back to the previous state, and print something else.

What I've tried:

JButton b = new JButton("First");
b.setBackground(Color.GREEN);
b.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
b.setBackground(Color.RED);
b.setText("Second");
System.out.println("You've clicked the button");
}
if(b.getModel.isPressed){
b.setBackground(Color.GREEN);
b.setText("Second");
System.out.println("You're back");
}


The problem is that the button doesn't go back to the previous state with the color (green) and text, and I don't how to handle that.

Answer

First of all, you shouldn't be using a MouseListener to do these things, because a better listener, ActionListener, was built specifically to be used with JButtons and similar entities to notify programs that a button has been pressed.

Having said that, sure you can add multiple ActionListeners (or MouseListeners) to a JButton, or you can have an ActionListener change its behaviors depending on the state of the program (usually meaning the values held by fields of the class).

A problem with your code and question is that I don't see when you expect or want the button to change its color back to green. If after a certain period of time, then have your ActionListener start a Swing Timer that changes the button's color back to green after x milliseconds.

Edit: I see, you want to toggle color -- then use a boolean field that you toggle or check the button's current color and base the listener's response based on that color.

example

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ToggleColor extends JPanel {

    public ToggleColor() {
        JButton button = new JButton(new MyButtonAction());
        button.setBackground(Color.GREEN);
        add(button);
    }

    private static void createAndShowGui() {
        ToggleColor mainPanel = new ToggleColor();

        JFrame frame = new JFrame("ToggleColor");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class MyButtonAction extends AbstractAction {
    // !! parallel arrays being used below -- avoid if possible
    private static final String[] TEXT = {"First", "Second", "Third"};
    private static final Color[] COLORS = {Color.GREEN, Color.RED, new Color(108, 160, 220)};
    private int index = 0;

    public MyButtonAction() {
        super(TEXT[0]);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        index++;
        index %= TEXT.length;
        putValue(NAME, TEXT[index]);
        Component c = (Component) e.getSource();
        c.setBackground(COLORS[index]);
    }
}

This uses an AbstractAction class which is like an ActionListener but on "steroids"