2

I have a chessboard with 64 JPanels representing each square on the board. The pieces are represented using JLabels which are placed on the JPanels. I am trying to remove all the JLabels off the board. I am confused why this doesn't work:

private void removePieces()
{
    for(int i = 0; i < 64; i ++)
    {       
        Component c = chessBoard.getComponent(i);
        if(c instanceof JLabel)
        {
            Container parent = c.getParent();
            parent.remove((JLabel)c);
            parent.revalidate();
            parent.repaint();
        }
    }
}

chessboard is the big JPanel with the 64 JPanels inside it. After some debugging it looks like the if loop is never being entered. I don't understand why it wouldn't enter the if loop if one of the components is a JLabel?

SKLAK
  • 3,825
  • 9
  • 33
  • 57

3 Answers3

2

Why remove the labels, rather than simply set the icon to null or text to ""?

E.G. using text for the pieces.

Chessboard

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.border.LineBorder;

class ChessBoard2 {

    static ChessMoveMouseListener cmml = new ChessMoveMouseListener();
    /** Unicode strings for chess pieces & empty string for blank squares. */
    static String[][] pieces = {
        {"\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659"},
        {"\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F"},
        {""}
    };
    static int[] order = new int[]{2, 4, 3, 0, 1, 3, 4, 2};
    static int[] pawns = new int[]{5, 5, 5, 5, 5, 5, 5, 5};
    static int[] blank = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
    static int white = 0;
    static int black = 1;
    static int space = 2;

    public static JLabel getColoredLabel(String string, int color) {
        JLabel l = new JLabel(string);
        l.setFont(l.getFont().deriveFont(50f));
        Color c = (color % 2 == 0 ? Color.WHITE : Color.LIGHT_GRAY);
        l.setBackground(c);
        l.setOpaque(true);
        l.addMouseListener(cmml);

        return l;
    }

    public static void addRowToContainer(
            Container c,
            int[] order,
            int row,
            int count) {

        for (int ii : order) {
            c.add(getColoredLabel(pieces[row][ii], count++));
        }
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JPanel chessboard = new JPanel(new GridLayout(0, 8, 1, 1));
                chessboard.setBackground(Color.BLACK);
                chessboard.setBorder(new LineBorder(Color.BLACK));

                int count = 0;
                // black pieces..
                addRowToContainer(chessboard, order, black, count);
                addRowToContainer(chessboard, pawns, black, ++count);
                // middle squares..
                addRowToContainer(chessboard, blank, space, ++count);
                addRowToContainer(chessboard, blank, space, ++count);
                addRowToContainer(chessboard, blank, space, ++count);
                addRowToContainer(chessboard, blank, space, ++count);
                // white pieces..
                addRowToContainer(chessboard, pawns, white, ++count);
                addRowToContainer(chessboard, order, white, ++count);

                JOptionPane.showMessageDialog(null, chessboard,
                        "Click two squares to move from/to",
                        JOptionPane.INFORMATION_MESSAGE);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

class ChessMoveMouseListener extends MouseAdapter {

    String s = null;

    @Override
    public void mouseClicked(MouseEvent e) {
        JLabel l = (JLabel) e.getSource();
        if (s == null) {
            if (l.getText().trim().length() > 0) {
                s = l.getText();
                l.setText("");
            }
        } else {
            l.setText(s);
            s = null;
        }
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • The problem is figuring out which panels actually have a label. If I just loop through the whole 64 panels and set the label to null, I'll get errors because some panels don't have labels. – SKLAK Sep 19 '13 at 14:42
  • *"The problem is figuring out which panels actually have a label"* I forgot to add a 'remove all pieces button', but note there is only a single `JPanel` in my example. Further, ***every*** space in the `GridLayout` of that panel has a `JLabel`! Are you not capable of progressing the problem from that? – Andrew Thompson Sep 19 '13 at 14:47
  • hmm.. In my implementation I didn't put a JLabel on every panel. Just the panels which have a piece on them contain a jlabel. – SKLAK Sep 19 '13 at 15:12
  • So.. change your implementation is my recommendation. Note how neat, clean and easy my example is. In less than 100 LOC, it can set up a complete chessboard that allows the user to move chess pieces. It would only require around 10-20 more LOC to 'clear the board' as you seem to want. – Andrew Thompson Sep 19 '13 at 15:14
  • 2
    BTW - I'd have thought my effort so far (an SSCCE with screenshot) might have earned me an up-vote. At least from the person that asked the question, and if only for the effort. As far as your design goes if you want to persist with that approach, I suggest you edit the question to include your own SSCCE. I refuse to work with uncompilable code snippets on a topic like this, where making a self contained example is trivial. – Andrew Thompson Sep 19 '13 at 15:23
  • 1
    +1 for an _authentic_ [sscce](http://sscce.org/), as well as a nice lookup table. – trashgod Sep 19 '13 at 15:32
  • Ok, so I added an empty JLabel at every panel when the board initializes. But I am confused about how to set the icon of the labels where there should be a piece. I am trying: private void drawPiece(String currPiece, int j) { JLabel piece = (JLabel)chessBoard.getComponent(j); piece.setIcon(new ImageIcon("C:/path/to/pics/" + currPiece)); } – SKLAK Sep 19 '13 at 15:35
  • I get the error that the JPanel can't be cast to a JLabel. k I gave you an upvote. sorry about that. – SKLAK Sep 19 '13 at 15:37
  • *"But I am confused about.."* ..SSCCE? – Andrew Thompson Sep 19 '13 at 16:13
2

Looks like your trying to remove your JPanels from your chessboard if they are JLabels (which obviously makes no sense, and is why the if code is never firing). Instead you want to remove the chessBoard's components' JLabel component. Example below.

private void removePieces() {
        for(int i = 0; i < 64; i ++) {   
            if(chessBoard.getComponent(i) instanceof JPanel) {
            JPanel c = (JPanel)chessBoard.getComponent(i);
            c.removeAll();
            c.revalidate();
            c.repaint();
            }
        }
    }

I am using removeAll() because I am presuming your JPanels have no other components in them other than the potential JLabels.

Rudi Kershaw
  • 12,332
  • 7
  • 52
  • 77
  • Also consider updating the component in place, for [example](http://stackoverflow.com/a/12228640/230513). – trashgod Sep 19 '13 at 15:34
  • hmm says removeall is undefined for the type component – SKLAK Sep 19 '13 at 15:39
  • @SKLAK It seems to work fine on my end. I'm not really sure what to suggest. I am assuming chessBoard contains the 64 JPanels. – Rudi Kershaw Sep 19 '13 at 15:45
  • @SKLAK Sorry, my bad, that's because `Component` doesn't have a `removeAll()` even though `JPanel` does. You can't access `removeAll()` from a `Component` reference, even if it contains a `JPanel`. I will edit my code to reflect the change. – Rudi Kershaw Sep 19 '13 at 15:53
1

Think, when you're doing:

Component c = chessBoard.getComponent(i);

you're getting one of the JPanels, that contains your JLabels. And of course they are not instances of JLabel. So you need to get JLabel from that JPanel and then remove it.

Viktor Ozerov
  • 295
  • 3
  • 10
  • How would I grab the JLabel from the JPanel if I'm not sure the JPanel even has a JLabel. Basically, how would I check that the JPanel has a JLabel in it? – SKLAK Sep 19 '13 at 07:22
  • Also, I have used the instanceof before to check whether the jpanel contains a jlabel and it has worked. For example, I used it to check when the user moves a piece to an occupied jpanel. – SKLAK Sep 19 '13 at 07:27