Domanda

I have a program with many buttons, all of which will be performing the same function. I was wondering if there was a way to attach a single listener to all existing JButtons in the program.

È stato utile?

Soluzione

Something like:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class CalculatorPanel extends JPanel
{
    private JTextField display;

    public CalculatorPanel()
    {
        Action numberAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                display.setCaretPosition( display.getDocument().getLength() );
                display.replaceSelection(e.getActionCommand());
            }
        };

        setLayout( new BorderLayout() );

        display = new JTextField();
        display.setEditable( false );
        display.setHorizontalAlignment(JTextField.RIGHT);
        add(display, BorderLayout.NORTH);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(0, 5) );
        add(buttonPanel, BorderLayout.CENTER);

        for (int i = 0; i < 10; i++)
        {
            String text = String.valueOf(i);
            JButton button = new JButton( text );
            button.addActionListener( numberAction );
            button.setBorder( new LineBorder(Color.BLACK) );
            button.setPreferredSize( new Dimension(50, 50) );
            buttonPanel.add( button );

            KeyStroke pressed = KeyStroke.getKeyStroke(text);
            InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(pressed, text);
            button.getActionMap().put(text, numberAction);
        }
    }

    private static void createAndShowUI()
    {
//      UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );

        JFrame frame = new JFrame("Calculator Panel");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( new CalculatorPanel() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

The Action will get the source object from the Event so that it knows which button was clicked.

If you need to use if/else logic in your Action, then you should be creating a separate Action. Don't force code into one Action if it doesn't belong.

Altri suggerimenti

Simply add the ActionListener to the buttons.

For the specific action depending on the source, you can use what I wrote or use ActionCommands (which basically links certain components to 'commands' that are sent to the ActionListener on an event).

Here's a little example:

public class MyClass implements ActionListener
{
    JButton button1;
    JButton button2;
    JButton button3;

    public MyClass()
    {
        button1 = new JButton();
        button2 = new JButton();
        button3 = new JButton();

        button1.addActionListener(this);
        button2.addActionListener(this);
        button3.addActionListener(this);
    }

    @Override
    public void ActionPerformed(ActionEvent e)
    {
        //do stuff

        //if you want to do something depending on the button pressed
        //check the source
        if (e.getSource() == button1)
        {
            //do stuff
        }
    }

}

You Could...

Create a single instance of the ActionListner and apply it to all the buttons

You Could...

Make use if the Actions API, which will allow you to create a self contained ActionListerner, which also includes the details to configure the buttons as well.

There are many ways to do it.

Do you control creation of these buttons? If yes, create a factory and attach a listener before returning the object

Otherwise, you may traverse swing tree and check for instance of JButton and attach on a match

You can also think about ActionMap/InputMap approach where an action can be stored and invoked based on the focus policy.

Also, you may extend JButton....

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top