1

Okay so I am making a 2d array of JToggleButtons. I got the action listener up and going, but I have no way to tell which button is which.

If I click one, all it returns is something like

javax.swing.JToggleButton[,59,58,19x14,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@53343ed0,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=]

Is there anyway to stick some sort of item or number in the button object to associate each button? And then when the button is clicked I can retrieve that item or number that was given to it?

Here is my button generator code. (How could I make "int l" associate (and count) to each button made, when it is called, it will return that number, or something along those lines.

JToggleButton buttons[][] = new JToggleButton[row][col];
int l = 0;


        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                buttons[i][j] = new JToggleButton("");
                buttons[i][j].setSize(15,15);
                buttons[i][j].addActionListener(new e());
                panel.add(buttons[i][j]);
                l++;

            }
        }

ActionListner

public class e implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        System.out.println(source);
    }

}

variable "source" is what I use to get my data, so how can int l, be returned through "source" (as its unique value for the unique button clicked) as a button is clicked?

Thanks, -Austin

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Austin
  • 3,010
  • 23
  • 62
  • 97

4 Answers4

3

very simple way is add ClientProperty to the JComponent, add to your definition into loop e.g.

buttons[i][j].putClientProperty("column", i);
buttons[i][j].putClientProperty("row", j);
buttons[i][j].addActionListener(new MyActionListener());

rename e to the MyActionListener and change its contents

public class MyActionListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        JToggleButton btn = (JToggleButton) e.getSource();
        System.out.println("clicked column " + btn.getClientProperty("column")
                + ", row " + btn.getClientProperty("row"));
}

EDIT:

for MinerCraft clone isn't required to implements ony of Listeners, there is only about Icon, find out that in this code (don't implement any of Listeners anf remove used ItemListener)

enter image description here

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

public class ButtonsIcon extends JFrame {

    private static final long serialVersionUID = 1L;
    private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
    private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
    private Icon warnIcon = UIManager.getIcon("OptionPane.warningIcon");

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ButtonsIcon t = new ButtonsIcon();
            }
        });
    }

    public ButtonsIcon() {
        setLayout(new GridLayout(2, 2, 4, 4));

        JButton button = new JButton();
        button.setBorderPainted(false);
        button.setBorder(null);
        button.setFocusable(false);
        button.setMargin(new Insets(0, 0, 0, 0));
        button.setContentAreaFilled(false);
        button.setIcon((errorIcon));
        button.setRolloverIcon((infoIcon));
        button.setPressedIcon(warnIcon);
        button.setDisabledIcon(warnIcon);
        add(button);

        JButton button1 = new JButton();
        button1.setBorderPainted(false);
        button1.setBorder(null);
        button1.setFocusable(false);
        button1.setMargin(new Insets(0, 0, 0, 0));
        button1.setContentAreaFilled(false);
        button1.setIcon((errorIcon));
        button1.setRolloverIcon((infoIcon));
        button1.setPressedIcon(warnIcon);
        button1.setDisabledIcon(warnIcon);
        add(button1);
        button1.setEnabled(false);

        final JToggleButton toggleButton = new JToggleButton();
        toggleButton.setIcon((errorIcon));
        toggleButton.setRolloverIcon((infoIcon));
        toggleButton.setPressedIcon(warnIcon);
        toggleButton.setDisabledIcon(warnIcon);
        toggleButton.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (toggleButton.isSelected()) {
                } else {
                }
            }
        });
        add(toggleButton);

        final JToggleButton toggleButton1 = new JToggleButton();
        toggleButton1.setIcon((errorIcon));
        toggleButton1.setRolloverIcon((infoIcon));
        toggleButton1.setPressedIcon(warnIcon);
        toggleButton1.setDisabledIcon(warnIcon);
        toggleButton1.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (toggleButton1.isSelected()) {
                } else {
                }
            }
        });
        add(toggleButton1);
        toggleButton1.setEnabled(false);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • be sure that there are another two ways (AFAIK) how to do it correctly, maybe you have to wait – mKorbel Feb 15 '12 at 20:41
  • Okay another question. I have this added on. if (bombloc == true) { buttons[i][j].putClientProperty("bomb", true); } else { buttons[i][j].putClientProperty("bomb", false); } How do I check to see if its true, I know I can click it and it says true, but how do I make an "if" statement via the btn.getClientProperty? – Austin Feb 15 '12 at 20:45
  • Nevermind I got that too work. I guess I just have one last question with how the actionListener is working. I have imageicons for stuff, how do I get the current btn (if its a bomb) to display the bomb symbol? I got it say if its a bomb and the imagecons are all loaded, I just don't know how to get the icon to update I.E. btn.setIcon(bombimage); <- that says the variable is nonexistent since its in the engine class. – Austin Feb 15 '12 at 21:16
  • @Austin for MineCraft clone isn't necessary to implement ActionListener, there you have to only setIcon and to check if isSelected, please see my edit – mKorbel Feb 15 '12 at 21:44
  • ok, I get that and I have it working. And now I have another question I am searching for, how do I register a "rick-click". We have to use that to lay down our flags on minesweeper. – Austin Feb 15 '12 at 21:53
  • would I just add this to the MyActionListener I created then? like...in the same class? Or make a new class? – Austin Feb 15 '12 at 23:13
1

Just add the row and column data to each listener. You could add an explicit constructor, but I suggest adding a little method (which may have more added to it later).

            buttons[i][j].addActionListener(e(i, j));
...
private ActionListener e(final int i, final int j) {
    return new ActionListener() {
        // i and j available here
        ...

(In JDK8 you should be able to use a lambda to reduce the syntax clutter.)

And then renaming it with a better name.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

I made a minesweeper game and ran into a similar problem. One of the only ways you can do it, is to get the absolute location of the clicked button, then divide that by the x and y between buttons, so for me it was

if ((e.getComponent().getX() != (randx) * 25 && e.getComponent().getY() != (randy) * 25) &&bomb[randx][randy] == false) {

This code was to check if the area had bombs. So I had 25 x and y difference between location of bombs. That will just give you a general idea on how to do this.

I believe: (x - x spacing on left side) / buffer - 1 would work.

  • I am doing minesweeper too! But isn't there something simpler to just label each button with? (in the background that is) – Austin Feb 15 '12 at 20:28
  • Well, besides that one, you can go through a list of all the buttons and compare it to the Component, if it lines up you are in. The major problem is, the mouse-clicked point is relevant to the component clicked, not the full Frame, so you have to get the component to make it unique. –  Feb 15 '12 at 20:39
0

Instead of 'e.getSource()' you can always call 'e.getActionCommand()'. For each button you can specify this by:

JButton button = new JButton("Specify your parameters here"); /*you get these from getActionCommand*/
button.setText("title here"); /*as far as I remember*/
Tõnis Ojandu
  • 3,486
  • 4
  • 20
  • 28
  • what I meant is that you these parameters are replied to getActionCommand() method for the specified ActionListener instance – Tõnis Ojandu Feb 15 '12 at 20:20
  • But that adds text to the buttons, I want them to be blank. This is a minesweeper game. – Austin Feb 15 '12 at 20:27