Java: Can't get checker pieces to properly display

Discussion in 'Mac Programming' started by jsmwoolf, Oct 19, 2011.

  1. jsmwoolf macrumors regular

    Joined:
    Aug 17, 2011
    #1
    I'm trying to create a checkers game and I'm diving a bit deeper with drawing graphics. The checker pieces do appear, but the original board that it was on wasn't really realistic to a checkerboard. So I successfully imitated the board, but the pieces don't appear. I did some research and found this tutorial from the oracle website. It appears that I need a JLayeredPane and my (bad) book appears to not cover this. I looked at the tutorial and tried to make it work in the project that I'm working on, but I hit a dead end because it didn't work.

    Code:
    import javax.swing.*;
    import java.awt.*;
    
    public class Checkers {
    	
    	JFrame window = new JFrame();
    	Control control = null;
    	
    	JPanel row1 = new JPanel();
    	JButton start = new JButton("Start");
    	JComboBox difficulty = new JComboBox();
    	JCheckBox AI = new JCheckBox("AI");
    	
    	JPanel row2 = new JPanel();
    	Cell[][] cell = null;
    	
    	boolean currentStatus=true;
    	
    	 public Checkers()
    	{
    		 control = new Control(this);
    		 cell = new Cell[8][8];
    		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		window.setSize(300,370);
    		window.setResizable(false);
    		FlowLayout layout = new FlowLayout();
    		window.setLayout(layout);
    		
    		FlowLayout layout1 = new FlowLayout();
    		row1.setLayout(layout1);
    		difficulty.addItem("Easy");
    		difficulty.addItem("Normal");
    		difficulty.addItem("Hard");
    		row1.add(difficulty);
    		row1.add(AI);
    		AI.setSelected(false);
    		row1.add(start);
    		window.add(row1);
    		
    		GridLayout layout2 = new GridLayout(8,8);
    		row2.setLayout(layout2);
    		for(int x =0; x < 8; x++)
    		{
    			currentStatus = (currentStatus ==true? false:true); //if the status is true, then it'll turn to false and vis-versa 
    			for(int y=0; y < 8; y++)
    			{
    			cell[x][y] = new Cell();
    			currentStatus = (currentStatus ==true? false:true); //if the status is true, then it'll turn to false and vis-versa 
    			cell[x][y].isBlack = (currentStatus==true?false:true); //draws it either black or leave it
    			row2.add(cell[x][y]);
    			}
    		}
    		row2.setPreferredSize(new Dimension(32*8,32*8));
    		window.add(row2);
    		
    		start.addActionListener(control);
    		window.setVisible(true);
    	}
    	
    	public static void main(String[] args) {
    		Checkers game = new Checkers();
    	}
    
    }
    
    class Cell extends JPanel
    {
    	int pieceType=0;
    	boolean isBlack=false;
    	Piece piece = null;
    	JLayeredPane layer = new JLayeredPane();
    	public Cell()
    	{
    		layer.setPreferredSize(new Dimension(31,31));
    		piece = new Piece(this,pieceType);
    		layer.add(piece,10);
    	}
    	public void paintComponent(Graphics g)
    	{
    		super.paintComponents(g);
    		if(pieceType!=0)
    		{
    			layer.setLayer(piece, 10);
    		}
    		if(isBlack==true)
    		{
    			g.setColor(Color.black);
    			g.fillRect(0, 0, 31, 31);
    		}
    		else
    		{
    			g.setColor(Color.white);
    			g.fillRect(0, 0, 31, 31);
    		}
    	}
    	
    }
    
    class Piece extends JComponent
    {
    	Cell control = null;
    	int pieceType=0;
    	public Piece(Cell control, int piece)
    	{
    		this.control = control;
    		pieceType = piece;
    	}
    	
    	public void paintComponent(Graphics g)
    	{
    		super.paintComponents(g);
    		if(pieceType ==1)
    		{
    			g.setColor(Color.darkGray);
    		}
    		else
    		{
    			g.setColor(Color.red);
    		}
    		g.fillOval(0, 0, 31, 31);
    	}
    }
    
    Code:
    import java.awt.event.*;
    public class Control implements ItemListener, ActionListener{
    	Checkers game;
    	
    	int[][] theBoard = new int[8][8];
    	
    	public Control(Checkers game)
    	{
    		this.game = game;
    	}
    	public void actionPerformed(ActionEvent input) {
    	Object current = input.getSource();
    	if(current.equals(game.start))
    	{
    		game.AI.setEnabled(false);
    		game.difficulty.setEnabled(false);
    		game.start.setEnabled(false);
    		//Sets up the board for player 2
    		theBoard[7][0] = 1;
    		theBoard[7][2] = 1;
    		theBoard[7][4] = 1;
    		theBoard[7][6] = 1;
    		theBoard[6][1] = 1;
    		theBoard[6][3] = 1;
    		theBoard[6][5] = 1;
    		theBoard[6][7] = 1;
    		theBoard[5][0] = 1;
    		theBoard[5][2] = 1;
    		theBoard[5][4] = 1;
    		theBoard[5][6] = 1;
    		//Sets up the board for player 1
    		theBoard[0][1] = 2;
    		theBoard[0][3] = 2;
    		theBoard[0][5] = 2;
    		theBoard[0][7] = 2;
    		theBoard[1][0] = 2;
    		theBoard[1][2] = 2;
    		theBoard[1][4] = 2;
    		theBoard[1][6] = 2;
    		theBoard[2][1] = 2;
    		theBoard[2][3] = 2;
    		theBoard[2][5] = 2;
    		theBoard[2][7] = 2;
    		
    		for(int x = 0; x < 8;x++)
    		{
    			for(int y=0; y < 8; y++)
    			{
    			game.cell[x][y].pieceType = theBoard[x][y];
    			game.cell[x][y].repaint();
    			}
    		}
    	}
    	}
    
    	@Override
    	public void itemStateChanged(ItemEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    JPanel Cell holds the space for the JComponent Piece, but would this even be necessary?

    This is my very first time dealing with JLayeredPane and this is more of a step up to Connect4, graphic-wise, because it tends to require layers whereas Connect4 doesn't require it. Sure I don't have to use multilayer in Checkers, but it's a new concept and it'll help me with future projects. Any ideas on how to make this work?
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    The red-hilited code is wrong.

    You should not be calling paintComponents (plural) from paintComponent (singular).


    You don't need a layered pane, either. All you need is a Cell that can draw the right thing for different states. The states are:
    1. Unoccupied.
    2. Occupied by red player.
    3. Occupied by black player.

    In all states, a Cell is either a red square or a black square. This doesn't change. Only the cell's occupied state changes.

    If a cell is a red square, it has a red background. If a cell is a black square, it has a black background. The shape is always a square. It always draws the background before it draws any player-piece occupying the cell.

    After drawing the cell background (red or black), the cell checks for occupied state. If unoccupied, it's done. Otherwise draw a circle in the correct color for the player occupying the square.
     
  3. jsmwoolf thread starter macrumors regular

    Joined:
    Aug 17, 2011
    #3
    Thanks for catching that.

    And I found out that you can simply use the set background instead of using fillOval. However, when should you use JLayeredPane?
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    You don't need it here. Why add complexity that isn't needed?

    Did you go through the JLayeredPane tutorial? The whole thing, step by step? If so, then you'd know when you should use it, and you'd know how to use it.

    The way your code is written now, the use of JLayeredPane is completely wrong. You're not even adding the layered pane to another visible container, so neither it nor its contents will appear. If you don't know why that's a problem, then you don't really understand how Swing or AWT works, and you should review the basics of which components have to be added to other components in order to appear on-screen.
     

Share This Page