Frage

I'm trying to make a chess-board kind of thing with each tile being a JButton. I want to add the same actionListener to every button. Here's the code:

package checker;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class mainClass extends JFrame   {

JPanel board = new JPanel();
ActionListener btnPrs = new btnPressed();


    public mainClass()
    {

        board.setLayout(new GridLayout(8,8,0,0));
        for(int i = 0; i<8; i++)
            for(int j = 0; j<8; j++)
            {
                if( i%2 == 0 && j%2 == 0 || i%2 == 1 && j%2 == 1)
                {   
                    board.add(new DrawWhite());
                    //board.add(new DrawWhite().addActionListener(btnPrs));

                }
                else board.add(new DrawBlack());
            }

        add(board);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        mainClass frame = new mainClass();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,400);
        frame.setVisible(true);
        frame.setTitle("Checker");
        frame.setLocationRelativeTo(null);

    }

    class DrawWhite extends JButton
    {
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            g.setColor(Color.WHITE);
            g.fillRect(0,0, 50,50);
            }       
    }

    class DrawBlack extends JButton
    {
    protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            g.setColor(Color.BLACK);
            g.fillRect(0, 0, 50, 50);

        }
    }


    class btnPressed implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent e) {

            System.out.println("pressed!");

        }
     }

     }

I don't want to explicitly define 64 buttons and add ActionListeners to each of them manually. I tried they way that is included as a comment on line 23. Is there a proper way to do it?

Any help would be highly appreciated.

War es hilfreich?

Lösung

Just store the button in a temporary variable:

DrawWhite dw = new DrawWhite();
dw.addActionListener(btnPrs);
board.add(dw);

Andere Tipps

If you really want "each tile being a JButton" then yes, you will need to define 64 JButtons, since the same component can't be added twice to its parent.

But if what you really need is that each tile is clickable, you will need to add no JButton at all. Use just a custom JPanel for the whole board, overriding its paintComponent method to drawd black and white squares. A single mouseListener attached to this JPanel could tell black from white tiles based on the x and y coordinates.

Working code follows:

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

public class mainClass extends JFrame   {

JPanel board = new BoardPanel();
MouseListener btnPrs = new btnPressed();


    public mainClass()
    {
        board.addMouseListener(btnPrs);
        add(board);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        mainClass frame = new mainClass();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,400);
        frame.setVisible(true);
        frame.setTitle("Checker");
        frame.setLocationRelativeTo(null);

    }

    private Color blackOrWhite(int i, int j) {
        return (i + j) % 2 == 0 ? 
                Color.WHITE
                : Color.BLACK;
    }


    class BoardPanel extends JPanel
    {
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    Color color = blackOrWhite(i, j);

                        g.setColor(color);
                        g.fillRect(i * 50, j * 50, 50, 50);

                    }
                }
            }
    }

    class btnPressed extends MouseAdapter
    {

        @Override
        public void mouseClicked(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            System.out.println("pressed!");
            System.out.println(blackOrWhite(x/50, y/50));
        }
     }

}

Bad thing is that you loose the "resizability" of JButtons in a BorderLayout. Also, you can no longer activate a tile by keyboard (as you could with JButtons), just by mouse clicks. Good thing is that you now have way less Objects instantiated, which brings a better memory footprint.

Hope it's useful.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top