I have created a program to add an ImageIcon to the next empty JLabel, the compiler shows no errors so why isn't this working? The setEmptySpace contains a loop that returns an empty space and the getCar method is supposed to set the icon.
package CarPark;
//add imports
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Park extends JPanel
{
//declare a JLabel array for parking space
JLabel[] parkingSpace;
//declare ImageIcon class for cars
ImageIcon car;
public Park()
{
//create a new instance of the parking space array with 12 spaces
parkingSpace = new JLabel[12];
//populate array
for (int i = 0; i < parkingSpace.length; i++)
{
//create parking space JLabels
//parkingSpace[i] = new JLabel(String.valueOf(i + 1));
parkingSpace[i] = new JLabel();
//set parking space colour
parkingSpace[i].setBackground(new Color(85, 55, 170));
//make JLabels opaque
parkingSpace[i].setOpaque(true);
}
//create grid for parking space setting rows, columns, horizontal gap and vertical gap
this.setLayout(new GridLayout(4, 3, 4, 4));
//set background colour to white
this.setBackground(new Color(255, 255, 255));
//add 12 parking spaces to panel
for (int i = 0; i < 12; i++)
{
this.add(parkingSpace[i]);
//create a red border with a thickness of 4 pixels
parkingSpace[i].setBorder(BorderFactory.createLineBorder(Color.RED, 4));
}
}
//find an empty parking space
int setEmptySpace()
{
for(int i = 0; i < parkingSpace.length; i++)
{
if(parkingSpace[i] == null)
{
return i;
}
}
return -1;
}
//add car image to empty parking space
void getCar(int getEmptySpace)
{
car = new ImageIcon("car.png");
parkingSpace[getEmptySpace].setIcon(car);
}
}
Based on this from your constructor...
for (int i = 0; i < parkingSpace.length; i++) {
//create parking space JLabels
//parkingSpace[i] = new JLabel(String.valueOf(i + 1));
parkingSpace[i] = new JLabel();
//set parking space colour
parkingSpace[i].setBackground(new Color(85, 55, 170));
//make JLabels opaque
parkingSpace[i].setOpaque(true);
}
It's impossible for this...
int setEmptySpace() {
for (int i = 0; i < parkingSpace.length; i++) {
if (parkingSpace[i] == null) {
return i;
}
}
return -1;
}
to return anything other than -1, because every parkingSpace contains a JLabel
What I think you want to do, is check to see if the JLabel's icon property is null, for example
int setEmptySpace() {
for (int i = 0; i < parkingSpace.length; i++) {
if (parkingSpace[i].getIcon() == null) {
return i;
}
}
return -1;
}
I've tried simplifying my code into more methods that only do one thing each instead of trying to do multiple tasks per method. What I want to know is does the setCarIconToLabel() actually set the icon to a JLabel and if it doesn't how could it be altered. Also is this method the correct type since I don't think it should be void but I don't know what else to set it to?
//find an empty parking space and return it's number
int emptySpaceNo()
{
for(int i = 0; i < parkingSpace.length; i++)
{
System.out.println("Test method 1 Park P 1");
if(parkingSpace[i].getIcon() == null)
{
System.out.println("Test method 1 P 2");
return i;
}
}
return -1;
}
//return JLabel that is null
JLabel findEmptySpace()
{
return parkingSpace[emptySpaceNo()];
}
//create new car image icon
ImageIcon setCarIcon()
{
ImageIcon carIcon = new ImageIcon("car.png");
return carIcon;
}
//set car icon to JLabel parking space
void setCarIconToLabel()
{
findEmptySpace().setIcon(setCarIcon());
}
Related
I have the weirdest bug ever.
I have this puzzle game that moves puzzle pieces (which really are buttons with images attached to them).
Everything worked fine until I tried to change the text of some label (to indicate how many steps the player has done).
Everytime I call someControl.setText("text");, the puzzle pieces that moved are set back to the their first position. I have no idea why, but they just do.
Here's my window:
It consists of two panels, each uses a GridBagLayout.
The main frame uses a gridBagLayout as well, which consists of the two panels.
I know it's weird as hell, but I can't figure out what may cause this GUI bug. Any idea?
The pieces of code:
increaseSteps which is called everytime I click a puzzle button
void increaseSteps() {
_steps++;
_lblSteps.setText("Steps: " + _steps);
}
Creation of the puzzle panel (the left panel)
private JPanel puzzlePanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int i = 0; i < _splitImage.getSize(); i++)
for (int j = 0; j < _splitImage.getSize(); j++) {
int valueAtPos = _board.getMatrix()[i][j];
if (valueAtPos == 0)
continue;
int imageRow = _board.getImageRowFromValue(valueAtPos);
int imageCol = _board.getImageColFromValue(valueAtPos);
ImageIcon imageIcon = new ImageIcon(_splitImage.getImages()[imageRow][imageCol]);
JButton btn = new JButton(imageIcon);
_tileButtons[i][j] = new TileButton(btn, i, j);
btn.setPreferredSize(new Dimension(_splitImage.getImages()[i][j].getWidth(null),
_splitImage.getImages()[i][j].getHeight(null)));
// add action listener
btn.addActionListener(this);
btn.addKeyListener(this);
gbc.gridx = j;
gbc.gridy = i;
panel.add(_tileButtons[i][j].getButton(), gbc);
}
return panel;
}
actionPerformed:
#Override
public void actionPerformed(ActionEvent e) {
if (!(e.getSource() instanceof JButton))
return;
JButton btn = (JButton) e.getSource();
TileButton tile = getTileButtonFromBtn(btn);
if (tile == null)
return;
// check if we can move the tile
String moveDir = _board.canMoveTile(tile.getRow(), tile.getCol());
if (moveDir.equals("no"))
return;
increaseSteps();
int dirx = 0;
int diry = 0;
if (moveDir.equals("left")) {
dirx = -1;
_board.move("left", true);
tile.setCol(tile.getCol() - 1);
} else if (moveDir.equals("right")) {
dirx = 1;
_board.move("right", true);
tile.setCol(tile.getCol() + 1);
} else if (moveDir.equals("up")) {
diry = -1;
_board.move("up", true);
tile.setRow(tile.getRow() - 1);
} else { // down
diry = 1;
_board.move("down", true);
tile.setRow(tile.getRow() + 1);
}
moveButton(btn, dirx, diry, MOVE_SPEED);
if (_board.hasWon())
win();
}
moveButton: (moves the button in a seperate thread, calling btn.setLocation())
private void moveButton(JButton btn, int dirx, int diry, int speed) {
Point loc = btn.getLocation();
// get start ticks, calculate distance etc...
StopWatch stopper = new StopWatch();
int distance;
if (dirx != 0)
distance = _splitImage.getImages()[0][0].getWidth(null) * dirx;
else
distance = _splitImage.getImages()[0][0].getHeight(null) * diry;
if (speed > 0) {
// run the animation in a new thread
Thread thread = new Thread() {
public void run() {
int currentTicks;
int elapsed;
do {
int newX = loc.x;
int newY = loc.y;
elapsed = stopper.getElapsed();
int moved = (int) ((double) distance * (double) (elapsed / (double) speed));
if (dirx != 0)
newX += moved;
else
newY += moved;
btn.setLocation(newX, newY);
} while (elapsed <= MOVE_SPEED);
// make sure the last location is exact
btn.setLocation(loc.x + (dirx == 0 ? 0 : distance), loc.y + (diry == 0 ? 0 : distance));
}
};
thread.start();
}
else
btn.setLocation(loc.x + (dirx == 0 ? 0 : distance), loc.y + (diry == 0 ? 0 : distance));
}
You're trying to set the absolute position of a component via setLocation(...) or setBounds(...), one that is held by a container that uses a layout manager. This may work temporarily, but will fail if the container's layout manager is triggered to re-do the layout of its contained components. When that happens, the GridBagConstraints will take over and the components will move to their gridbag constraints assigned location.
The solution is to not do this, and instead to place the location of your components in concert with the layout managers used.
Another problem is that your current code is not Swing thread-safe since you're making Swing state changes from within a background thread. This won't always cause problems, but since it's a threading issue, risks causing intermittent hard to debug problems (ones that usually only occur when your boss or instructor are trying to run your code).
Possible solutions:
For a grid of images, you could use a grid of JLabels (or JButtons if you must) held in a container that uses GridLayout. When you need to reposition components, remove all components held by that JPanel, and then re-add, using the order of addition to help you position the components.
Easiest though would be to use a grid of non-moving JLabels, give them MouseListeners, and instead of moving the JLabels, remove and add Icons to them, including a blank Icon.
If you need to do Swing animation, use a Swing Timer to drive the animation. This will allow your code to make repetitive calls with delay between the calls, and with these calls being made on the Swing event thread, the EDT (event dispatch thread).
Demo proof of concept example code that shows swapping icons, but without animation, and without test of solution yet:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class ImageShuffle extends JPanel {
private static final int SIDES = 3;
public static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/5/5a/Hurricane_Kiko_Sep_3_1983_1915Z.jpg/"
+ "600px-Hurricane_Kiko_Sep_3_1983_1915Z.jpg";
private List<Icon> iconList = new ArrayList<>(); // shuffled icons
private List<Icon> solutionList = new ArrayList<>(); // in order
private List<JLabel> labelList = new ArrayList<>(); // holds JLabel grid
private Icon blankIcon;
public ImageShuffle(BufferedImage img) {
setLayout(new GridLayout(SIDES, SIDES, 1, 1));
fillIconList(img); // fill array list with icons and one blank one
Collections.shuffle(iconList);
MyMouseListener myMouse = new MyMouseListener();
for (Icon icon : iconList) {
JLabel label = new JLabel(icon);
label.addMouseListener(myMouse);
add(label);
labelList.add(label);
}
}
private class MyMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
JLabel selectedLabel = (JLabel) e.getSource();
if (selectedLabel.getIcon() == blankIcon) {
return; // don't want to move the blank icon
}
// index variables to hold selected and blank JLabel's index location
int selectedIndex = -1;
int blankIndex = -1;
for (int i = 0; i < labelList.size(); i++) {
if (selectedLabel == labelList.get(i)) {
selectedIndex = i;
} else if (labelList.get(i).getIcon() == blankIcon) {
blankIndex = i;
}
}
// get row and column of selected JLabel
int row = selectedIndex / SIDES;
int col = selectedIndex % SIDES;
// get row and column of blank JLabel
int blankRow = blankIndex / SIDES;
int blankCol = blankIndex % SIDES;
if (isMoveValid(row, col, blankRow, blankCol)) {
Icon selectedIcon = selectedLabel.getIcon();
labelList.get(selectedIndex).setIcon(blankIcon);
labelList.get(blankIndex).setIcon(selectedIcon);
// test for win here by comparing icons held by labelList
// with the solutionList
}
}
private boolean isMoveValid(int row, int col, int blankRow, int blankCol) {
// has to be on either same row or same column
if (row != blankRow && col != blankCol) {
return false;
}
// if same row
if (row == blankRow) {
// then columns must be off by 1 -- they're next to each other
return Math.abs(col - blankCol) == 1;
} else {
// or else rows off by 1 -- above or below each other
return Math.abs(row - blankRow) == 1;
}
}
public void shuffle() {
Collections.shuffle(iconList);
for (int i = 0; i < labelList.size(); i++) {
labelList.get(i).setIcon(iconList.get(i));
}
}
}
private void fillIconList(BufferedImage img) {
// get the width and height of each individual icon
// which is 1/3 the image width and height
int w = img.getWidth() / SIDES;
int h = img.getHeight() / SIDES;
for (int row = 0; row < SIDES; row++) {
int y = (row * img.getWidth()) / SIDES;
for (int col = 0; col < SIDES; col++) {
int x = (col * img.getHeight()) / SIDES;
// create a sub image
BufferedImage subImg = img.getSubimage(x, y, w, h);
// create icon from the image
Icon icon = new ImageIcon(subImg);
// add to both icon lists
iconList.add(icon);
solutionList.add(icon);
}
}
// create a blank image and corresponding icon as well.
BufferedImage blankImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
blankIcon = new ImageIcon(blankImg);
iconList.remove(iconList.size() - 1); // remove last icon from list
iconList.add(blankIcon); // and swap in the blank one
solutionList.remove(iconList.size() - 1); // same for the solution list
solutionList.add(blankIcon);
}
private static void createAndShowGui(BufferedImage img) {
JFrame frame = new JFrame("ImageShuffle");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ImageShuffle(img));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
URL imgUrl = null;
BufferedImage img;
try {
imgUrl = new URL(IMG_PATH);
img = ImageIO.read(imgUrl);
SwingUtilities.invokeLater(() -> createAndShowGui(img));
} catch (IOException e) {
e.printStackTrace();
}
}
}
If I wanted animation, again, I'd raise the icon into the JFrame's glasspane, animate it to the new position using a Swing Timer, and then place the icon into the new JLabel. I'd also disable the MouseListener using a boolean field, a "flag", until the animation had completed its move.
Ok. So I'm supposed to build a GUI for my connect 4 program. (Please excuse the chunks of code here and there) I have shortened this program for your reading and I have excluded some code that doesn't have issues. I'm trying to get my JPanel down to the Connect4(). How can I access public TestPane() so I can update the GUI from Connect4().
I am not allowed to use anything Static.
LINE 153 WAS WHERE I WAS GOING TO ATTEMPT TO UPDATE THE GUI
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.GridLayout;
public class Connect4 extends JPanel{
public boolean col1 = false;
public int buttonPressed = 10;
public class TestPane extends JPanel{
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < 7; row++) {
for (int col = 0; col < 8; col++) {
//setBackground(Color.BLUE);
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < 7) {
if (col < 8) {
border = new MatteBorder(1, 1, 1, 1, Color.BLACK);
} else {
border = new MatteBorder(1, 1, 1, 1, Color.BLACK);
}
} else {
if (col < 8) {
border = new MatteBorder(1, 1, 1, 1, Color.BLACK);
} else {
border = new MatteBorder(1, 1, 1, 1, Color.BLACK);
}
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
//JUST TO TEST THAT THE SQUARES ARE WORKING. THEY ARE BUT NOT WITH MY PROGRAM
gbc.gridx = 3;
gbc.gridy = 2;
CellPane cellPaneP1 = new CellPane();
cellPaneP1.setBackground(Color.BLUE);
add(cellPaneP1,gbc);
gbc.gridx = 5;
gbc.gridy = 4;
CellPane cellPaneP2 = new CellPane();
cellPaneP2.setBackground(Color.RED);
add(cellPaneP2,gbc);
}
}
}
public Connect4(){
JOptionPane.showMessageDialog(null, "Welcome to Connect Four\nThis game will require 2 players\nPlease Enter your names");
Player p1 = new Player();
Player p2 = new Player();
String p1Name = JOptionPane.showInputDialog("Enter your name Player 1");
p1.setName(p1Name);
String p2Name = JOptionPane.showInputDialog("Enter your name Player 2");
p2.setName(p2Name);
JOptionPane.showMessageDialog(null,p1.getName()+ " vs " + p2.getName()+". \nThis is going to be EPIC!!!");
System.out.println(p1.getName()+ " vs " + p2.getName()+". \nThis is going to be EPIC!!!");
int winner =0;
//Create Our board
Board con4Bor= new Board();
//con4Bor.setSize(7,8);]
//Fill our board with '_' to represent empty spaces
con4Bor.fillBoard();
//Randomly Select Player to go first
int i = 0;
int p1p2 = (int)(Math.random()*2+1);
if(p1p2 == 1)
System.out.println(p1.getName() + " was selected at random to go first");
else
System.out.println(p2.getName() + " was selected at random to go first");
JButton column1 = new JButton(new AbstractAction("Column 1"){
#Override
public void actionPerformed(ActionEvent a){
buttonPressed = 1;
}
});
while(winner == 0){
if(p1p2 == 3){
p1p2--;
}
con4Bor.printOutBoard();
//printDiag(c4b);
int playerSelection = 10;
//System.out.println(p1p2);
if(p1p2 == 1){
System.out.println(p1.getName()+": it is now your turn\nplease choose a column");
}
else{
System.out.println(p2.getName()+": it is now your turn\nplease choose a column");
}
System.out.println("Which Column do you want to insert? Column 1, 2, 3, 4, 5, 6, 7 or 8?");
playerSelection = 1;
while(playerSelection != 1 && buttonPressed != 2 && buttonPressed != 3 && buttonPressed != 4 && buttonPressed != 5 && buttonPressed != 6 && buttonPressed != 7 && buttonPressed != 8){
System.out.println(buttonPressed);
playerSelection = 1;//buttonPressed;
}
if(playerSelection == 1){
********************************************************************************
********************************************************************************
***This is where I was poorly attempting to update my GUI if someone selected column 1 ***
********************************************************************************
********************************************************************************
i = 0;
con4Bor.insertCol(i, playerSelection-1, p1p2);
}
//WINNER DETECTION
if(p1p2 == 1){
if(con4Bor.weHaveAHorizontalWinner() == true || con4Bor.weHaveAVeritcalWinner() == true || con4Bor.weHaveADiagonalWinner()==true){
con4Bor.printOutBoard();
System.out.println(p1.getName()+" Wins!!!");
winner++;
}else{
p1p2 =3;
}
}
if(p1p2 == 2){
if(con4Bor.weHaveAHorizontalWinner() == true || con4Bor.weHaveAVeritcalWinner() == true || con4Bor.weHaveADiagonalWinner()==true){
con4Bor.printOutBoard();
System.out.println(p2.getName()+" Wins!!!");
winner++;
}else{
p1p2--;
}
}
}
}
public class CellPane extends JPanel {
private Color defaultBackground;
public CellPane() {
defaultBackground = getBackground();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
}
public static void main (String [] args){
new tester();
}
}
Try repaint() + revalidate() on JPanel after you added/removed/changed any element on it. Also read about MVC and best practices when creating desktop JAVA app.
I have successfully got a checkerboard to be put together using colored panels, but only when the user will input odd numbers for the rows and columns. Otherwise when inputing even numbers it just shows alternating colored columns. I'm struggling to figure out how to write a short segment that checks to see if it's odd or even by using the %2=0, with the result of even changing the color. Below is my code. Thanks, and take it easy on me I'm very new to programming! :-)
Also, I've created a separate ColorPanel class to build the colored panel, and then pull into into my main program. I didn't bother putting that code below.
import javax.swing.*;
import java.awt.*;
public class Checkerboard extends JPanel{
public static void main(String[] args) {
JFrame chBoard = new JFrame();
chBoard.setTitle("Checkerboard");
chBoard.setSize(800,800);
chBoard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String inputStr = JOptionPane.showInputDialog("Number of rows", "5");
if (inputStr == null) return;
int row = Integer.parseInt(inputStr);
inputStr = JOptionPane.showInputDialog("Number of columns", "5");
if (inputStr == null) return;
int col = Integer.parseInt(inputStr);
Container pane = chBoard.getContentPane();
pane.setLayout(new GridLayout(row, col));
Color BoxColor = Color.red;
for ( int counter = 1; counter <= row * col; counter++ )
{
if (BoxColor == Color.red)
BoxColor = Color.black;
else
BoxColor = Color.red;
ColorPanel panel = new ColorPanel(BoxColor);
pane.add(panel);
}
chBoard.setVisible(true);
}
}
Change your loop to:
for ( int x = 0; x < row; x++ ) {
for(int y = 0; y < col; y++) {
if((x + y)%2 == 0) {
BoxColor = Color.red;
} else {
BoxColor = Color.black;
}
...
}
}
Like I said, I'm new to programming but I'm really enjoying the learning experience. I hope this helps other people in their learning experience.
Anyways, I suppose I created more work for myself with the separate ColorPanel class. So instead of creating a separate ColorPanel class to build the colored panel, I just changed it to use the preexisting JPanel class to create the panel inside the main program. So instead of:
ColorPanel panel = new ColorPanel(BoxColor);
+ the ColorPanel class...
I put:
JPanel panel = new JPanel();
panel.setBackground(BoxColor);
within the main program and deleted the additional ColorPanel class.
Sorry for the redundancy, just wanting to explain myself clearly.
Also, thanks to Jason he really helped me figure out the idea of using the two
int x & y
to count the
row & col
and then add them together which enabled me to use the
%2=0
to figure out whether I was on the odd or even panel.
Hope this helps someone! :-)
Final code looks like this:
import javax.swing.*;
import java.awt.*;
public class Checkerboard extends JPanel{
public static void main(String[] args) {
JFrame chBoard = new JFrame();
chBoard.setTitle("Checkerboard");
chBoard.setSize(800,800);
chBoard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String inputStr = JOptionPane.showInputDialog("Number of rows", "5");
if (inputStr == null) return;
int row = Integer.parseInt(inputStr);
inputStr = JOptionPane.showInputDialog("Number of columns", "5");
if (inputStr == null) return;
int col = Integer.parseInt(inputStr);
Container pane = chBoard.getContentPane();
pane.setLayout(new GridLayout(row, col));
Color BoxColor = Color.red;
for ( int x = 0; x < row; x++ ) {
for(int y = 0; y < col; y++) {
if((x + y)%2 == 0) {
BoxColor = Color.red;}
else{
BoxColor = Color.black;}
JPanel panel = new JPanel();
panel.setBackground(BoxColor);
pane.add(panel);
}
chBoard.setVisible(true);
}
}
}
so i have this program that asks a user for a number of rows and columns and then makes it into a checker board but my issue is that it only works with odd numbers like if the user was to put in 9 and 9 again it would display a checkered board but if a even number is inputted it just shows columns of white and black
import javax.swing.*;
import java.awt.*;
public class Checkers {
public static void main(String[] args) {
JFrame theGUI = new JFrame();
theGUI.setTitle("Checkers");
String inputStr = JOptionPane.showInputDialog("Number of rows");
if (inputStr == null) return;
int rows = Integer.parseInt(inputStr);
inputStr = JOptionPane.showInputDialog("Number of Columns");
if (inputStr == null) return;
int cols = Integer.parseInt(inputStr);
theGUI.setSize(cols * 50 , rows * 50);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = theGUI.getContentPane();
pane.setLayout(new GridLayout(rows, cols));
for (int i = 1; i <= rows * cols ;i ++) {
if(i % 2 == 0){
ColorPanel panel = new ColorPanel(Color.white);
pane.add(panel);
}else{
ColorPanel panel = new ColorPanel(Color.black);
pane.add(panel);
}
}
theGUI.setVisible(true);
}
}
Your example identifies even numbers in a single loop. Instead, use nested loops to identify alternating tiles:
g.setColor(Color.lightGray);
…
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
if ((row + col) % 2 == 0) {
g.fillRect(col * TILE, row * TILE, TILE, TILE);
}
}
}
A complete example is seen here.
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?
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.
Why remove the labels, rather than simply set the icon to null or text to ""?
E.G. using text for the pieces.
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;
}
}
}
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.