1

I have a class called BoardSquare that is an inherited class of JButton. Each of the BoardSquare objects is stored in an array BoardSquare[][] boardsquares. I have used the following code

BoardSquare.boardSquares[j][i].add(new JLabel((j+1)+":"+(i+1)));

to add labels to each of the squares in the array according to their coordinates. I need them to have these labels(I think) so that I can identify them and addActionListeners, etc. How do I make the JLabels invisible so they don't show up in my JFrame?

Alternatively, how can I make the JLabel of each button an instance variable so that I can call JLabel.setVisible(false) but still use them when I add action listeners?

EDIT: If anyone's interested, it's for a Checkers Game.

Here are my classes:
GameWindow
BoardSquare
Checker
MyListener

aidandeno
  • 307
  • 1
  • 2
  • 16
  • 2
    This sounds like a possible [XY Problem](http://mywiki.wooledge.org/XyProblem). What is this all being used for? A MineSweeper game? What behaviors do you want the user to experience with your GUI and with this component? There may be a better approach to whatever it is you are trying to do, so let's try to help you find that approach. – Hovercraft Full Of Eels Sep 08 '14 at 13:13
  • I don't understand why you would want to add a label just to make it inivisible. If you just want to add actionlisteners why not just do `BoardSquare.boardSquares[j][i].addActionListener(...);`? – zero_dev Sep 08 '14 at 13:19
  • While I agree with most of the previous comments, I'll add two thoughts. 1) The simplest way to make a label invisible is to call `label.setText(""); label.setIcon(null);` 2) It is probably best to use `JButton` objects for the grid. E.G. as seen in this [chess GUI](http://stackoverflow.com/q/21142686/418556). – Andrew Thompson Sep 08 '14 at 13:34
  • @zero_dev This is my first ever GUI, so I'm obviously naive about a few things. I think I'd need the JLabel because when the action is performed, it would need to do things like check legal moves and attributes of the piece, all instance variables of elements at coords (i, j). – aidandeno Sep 08 '14 at 13:35
  • BTW - we can add an `ActionListener` to a `JButton`, but **not** a `JLabel`.. – Andrew Thompson Sep 08 '14 at 13:36
  • JButton extends BoardSquare. Doesn't that count? – aidandeno Sep 08 '14 at 13:38
  • 1
    *"JButton extends BoardSquare."* Sorry, only noticed the links to source just now. For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal, Complete, Verifiable Example). And post it here, rather than at paste bin. Also another tip: Tip: Be sure to add @zero_dev (or whoever, the `@` is important) to *notify* a person of a new comment. Exactly one person can be notified per comment. – Andrew Thompson Sep 08 '14 at 13:43

2 Answers2

3

Thank you for the edit. If this were my application, I'd probably do things very differently including,

  • Use a grid of JLabels not JButtons. I see no need to use JButtons, and a problem in that the button would not be as visually appealing as other possible solutions.
  • Either give the JLabel cells or the containing JPanel a MouseListener,
  • Have the JPanel cells have no Icon and thus be empty if no checker is on them,
  • Or have them hold an ImageIcon of an appropriately colored checker if they are not empty.
  • You could even animate the GUI by using the glass pane to hold a JPanel with an appropriate checker ImageIcon that the user can drag.

Note that if you absolutely have to use JButtons, then don't add JLabels to them. Instead simply set the JButton's Icon to null or to an appropriate Checker ImageIcon.


Edit
For example, a bad code example as a proof of concept. Try compiling and running this.

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;

import javax.swing.*;

@SuppressWarnings("serial")
public class Checkers extends JPanel {
   public static final int SIDE_LENGTH = 60;
   public static final int ROW_COUNT = 8;
   private static final String ROW = "row";
   private static final String COLUMN = "column";
   private static final Color LIGHT_COLOR = new Color(210, 180, 140);
   private static final Color DARK_COLOR = new Color(107, 68, 35);
   private Map<Checker, Icon> checkerIconMap = new EnumMap<Checker, Icon>(
         Checker.class);
   private JLabel[][] labelGrid = new JLabel[ROW_COUNT][ROW_COUNT];
   private Checker[][] checkerGrid = new Checker[ROW_COUNT][ROW_COUNT];

   public Checkers() {
      for (Checker checker : Checker.values()) {
         checkerIconMap.put(checker, createCheckerIcon(checker));
      }
      setLayout(new GridLayout(ROW_COUNT, ROW_COUNT));

      for (int row = 0; row < labelGrid.length; row++) {
         for (int col = 0; col < labelGrid[row].length; col++) {
            checkerGrid[row][col] = Checker.EMPTY;
            JLabel gridCell = new JLabel(checkerIconMap.get(Checker.EMPTY));
            gridCell.setOpaque(true);
            gridCell.putClientProperty(ROW, row);
            gridCell.putClientProperty(COLUMN, col);
            Color c = row % 2 == col % 2 ? LIGHT_COLOR : DARK_COLOR;
            gridCell.setBackground(c);
            add(gridCell);
            labelGrid[row][col] = gridCell;
         }
      }

      for (int i = 0; i < labelGrid.length / 2 - 1; i++) {
         for (int j = 0; j < labelGrid.length / 2; j++) {
            int row = i;
            int col = j * 2;
            col += row % 2 == 0 ? 1 : 0;
            labelGrid[row][col].setIcon(checkerIconMap.get(Checker.BLACK));
            checkerGrid[row][col] = Checker.BLACK;

            row = ROW_COUNT - row - 1;
            col = ROW_COUNT - col - 1;
            labelGrid[row][col].setIcon(checkerIconMap.get(Checker.RED));
            checkerGrid[row][col] = Checker.RED;
         }
      }

      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseListener(myMouseAdapter);
      addMouseMotionListener(myMouseAdapter);
   }

   private Icon createCheckerIcon(Checker checker) {
      BufferedImage img = new BufferedImage(SIDE_LENGTH, SIDE_LENGTH,
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      g2.setColor(checker.getColor());
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      int x = 3;
      int y = x;
      int width = SIDE_LENGTH - 2 * x;
      int height = width;
      g2.fillOval(x, y, width, height);
      g2.dispose();

      return new ImageIcon(img);
   }

   private class MyMouseAdapter extends MouseAdapter {
      private int selectedRow = -1;
      private int selectedCol = -1;
      private Checker selectedChecker = null;
      private JPanel glassPane = null;
      private Point p = null;
      private JLabel movingLabel = new JLabel(checkerIconMap.get(Checker.EMPTY));

      public MyMouseAdapter() {
         movingLabel.setSize(movingLabel.getPreferredSize());
         movingLabel.setVisible(false);
      }

      @Override
      public void mousePressed(MouseEvent e) {
         p = e.getPoint();
         for (int row = 0; row < labelGrid.length; row++) {
            for (int col = 0; col < labelGrid[row].length; col++) {
               JLabel gridCell = labelGrid[row][col];
               if (gridCell == getComponentAt(p)) {
                  if (checkerGrid[row][col] != Checker.EMPTY) {
                     selectedRow = row;
                     selectedCol = col;
                     selectedChecker = checkerGrid[row][col];
                     checkerGrid[row][col] = Checker.EMPTY;
                     labelGrid[row][col].setIcon(checkerIconMap.get(Checker.EMPTY));

                     JRootPane rootPane = SwingUtilities.getRootPane(Checkers.this);
                     glassPane = (JPanel) rootPane.getGlassPane();
                     glassPane.setVisible(true);
                     glassPane.setLayout(null);
                     movingLabel.setIcon(checkerIconMap.get(selectedChecker));
                     movingLabel.setVisible(true);
                     glassPane.add(movingLabel);
                     int x = p.x - SIDE_LENGTH / 2;
                     int y = p.y - SIDE_LENGTH / 2;
                     movingLabel.setLocation(x, y);
                  }
               }
            }
         }
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         if (selectedChecker == null) {
            return;
         }

         p = e.getPoint();
         if (!Checkers.this.contains(p)) {
            // if mouse releases and is totally off of the grid
            returnCheckerToOriginalCell();
            clearGlassPane();
            return;
         }

         for (int row = 0; row < labelGrid.length; row++) {
            for (int col = 0; col < labelGrid[row].length; col++) {
               JLabel gridCell = labelGrid[row][col];
               if (gridCell == getComponentAt(p)) {
                  if (isMoveLegal(row, col)) {
                     checkerGrid[row][col] = selectedChecker;
                     labelGrid[row][col].setIcon(checkerIconMap.get(selectedChecker));

                     // todo: check for jumped pieces...
                  } else {
                     // illegal move
                     returnCheckerToOriginalCell();
                  }
               }
            }
         }
         clearGlassPane();
      }

      // this code would go in the model class
      private boolean isMoveLegal(int row, int col) {
         if (checkerGrid[row][col] != Checker.EMPTY) {
            // trying to put a checker on another checker
            returnCheckerToOriginalCell();
         } else if (row == selectedRow && col == selectedCol) {
            // trying to put checker back in same position
            returnCheckerToOriginalCell();
         } else if (row % 2 == col % 2) {
            // invalid square
            returnCheckerToOriginalCell();
         } else {
            // TODO: more logic needs to go here to test for a legal move
            // and to remove jumped pieces

            return true;
         }
         return false;
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         if (selectedChecker == null || p == null) {
            return;
         }
         p = e.getPoint();
         int x = p.x - SIDE_LENGTH / 2;
         int y = p.y - SIDE_LENGTH / 2;
         movingLabel.setLocation(x, y);
      }

      private void clearGlassPane() {
         glassPane.setVisible(false);
         movingLabel.setVisible(false);
         selectedChecker = null;
         p = null;
         selectedCol = -1;
         selectedRow = -1;
      }

      private void returnCheckerToOriginalCell() {
         checkerGrid[selectedRow][selectedCol] = selectedChecker;
         labelGrid[selectedRow][selectedCol].setIcon(checkerIconMap.get(selectedChecker));
      }
   }

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

      JFrame frame = new JFrame("JLabelGrid");
      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(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class CheckerModel {

}

enum Checker {
   EMPTY(new Color(0, 0, 0, 0)), RED(Color.red), BLACK(Color.black);
   private Color color;

   private Checker(Color color) {
      this.color = color;
   }

   public Color getColor() {
      return color;
   }
}

Better Model-View example being worked on...

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    *"..the button would not be as visually appealing as other possible solutions."* What the huh? Given a button can effectively be invisible, as in the chess GUI, I don't see how a button could be any less beautiful than the icon it displays. – Andrew Thompson Sep 08 '14 at 13:38
  • @AndrewThompson: true, but perhaps it then goes to one of it just not feeling "right" to me. The cell isn't acting so much as a button but as a clickable location (again JLabel would work great) that holds an icon and does not get depressed. Maybe I'm just being stubborn because yes, it would work as a JButton with swapping icons (as I added to my answer actually before seeing your comment). But thanks for the comment! – Hovercraft Full Of Eels Sep 08 '14 at 13:40
  • *"that the user can drag."* Arrg.. What about your mouse challenged users? Just the other week I found myself with no mouse and was playing Solitaire using only the keyboard! – Andrew Thompson Sep 08 '14 at 13:40
  • 1
    @AndrewThompson: I'm sorry, I answered in ignorance and didn't know about your mouse challenge issues. I will try to be more sensitive to issues of this type in the future. ;) – Hovercraft Full Of Eels Sep 08 '14 at 13:42
  • 1
    *"I will try to be more sensitive.."* Happiness. :) – Andrew Thompson Sep 08 '14 at 13:45
  • @HovercraftFullOfEels I am eagerly awaiting your checkers 2.0! – aidandeno Sep 09 '14 at 14:42
0

Instead of adding the new Jlabel() directly to the array , make an instance first then add that ... i guess this is done in a loop so for example :

 JLabel lbl;
 for(....) {
lbl = new JLabel(new JLabel((j+1)+":"+(i+1));
lbl.addActionListener(new ActionListener(){

 public void actionPerformed(ActionEvent evt()){
  // TODO here
  }
 });
BoardSquare.boardSquares[j][i].add(lbl);
vlatkozelka
  • 909
  • 1
  • 12
  • 27