paint() problem

Hi.. I also made this post in the AWT section, but I think it belongs here, as i'm using mostly Swing. Sorry for any confusion.

I'm having a paint problem. In the Blackjack game i'm designing, I want an animation to take place so that a card can be seen moving from the deck and into the dealer's/player's hand. Here is the source for the entire class.

import javax.swing.JPanel;

import javax.swing.JButton;

import javax.swing.ImageIcon;

import java.awt.Color;

import java.awt.image.BufferedImage;

import java.awt.GridBagLayout;

import java.awt.GridBagConstraints;

import java.awt.FlowLayout;

import java.awt.Insets;

import java.awt.Component;

import java.awt.Graphics;

import java.awt.Dimension;

import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;

import javax.imageio.ImageIO;

import java.io.File;

import java.io.IOException;

publicclass BlackjackPanelextends JPanel

{

private Deck deck;

private CardPanel cp;

public BlackjackPanel()

{

deck =new Deck();

setLayout(new GridBagLayout());

//dark green

setBackground(new Color(0, 153, 51));

add(new LogoPanel(), getConstraints(0,0,1,1,GridBagConstraints.NORTHWEST));

add(new ButtonPanel(),getConstraints(0,2,1,1,GridBagConstraints.EAST));

cp =new CardPanel();

add(cp,getConstraints(4,0,5,5,GridBagConstraints.CENTER));

add(new PanelB(),getConstraints(9,0,1,1,GridBagConstraints.NORTHEAST));

}//end BlackjackPanel c'tor

//**********************************************************

private GridBagConstraints getConstraints(int gridx,

int gridy,int gridWidth,int gridHeight,int anchor)

{

GridBagConstraints c =new GridBagConstraints();

c.insets =new Insets(5, 5, 5, 5);

c.ipadx = 0;

c.ipady = 0;

c.gridx = gridx;

c.gridy = gridy;

c.gridwidth = gridWidth;

c.gridheight = gridHeight;

c.anchor = anchor;

return c;

}//end getConstraints

//*************************************************************

class LogoPanelextends JPanel

{

private BufferedImage logo;

public LogoPanel()

{

setPreferredSize(new Dimension(250,300));

setBackground(new Color(0, 153, 51));

//logo

try

{

logo = ImageIO.read(new File("logo.JPG"));

}catch(IOException e)

{

System.out.println("logo.JPG is missing. Terminating..");

System.exit(0);

}

repaint();

}//end LogoPanel c'tor

//*****************************************************************

publicvoid paint(Graphics g)

{

g.drawImage(logo,0,0,null);

}

}//end class LogoPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class ButtonPanelextends JPanelimplements ActionListener

{

private ImageIcon dealBtnPic;

private ImageIcon hitBtnPic;

private ImageIcon stayBtnPic;

private ImageIcon splitBtnPic;

private JButton deal;

private JButton hit;

private JButton stay;

private JButton split;

public ButtonPanel()

{

//setBackground(new Color(0, 153, 51));

setBackground(new Color(0,0,0));

setLayout(new GridBagLayout());

setPreferredSize(new Dimension(250, 300));

//load button icons

splitBtnPic =new ImageIcon("splitbtnpic.JPG");

dealBtnPic =new ImageIcon("dealbtnpic.JPG");

hitBtnPic =new ImageIcon("hitbtnpic.JPG");

stayBtnPic =new ImageIcon("staybtnpic.JPG");

//split button

split =new JButton("Split", splitBtnPic);

add(split);

//hit button

hit =new JButton("Hit", hitBtnPic);

add(hit);

//deal button

deal =new JButton("Deal", dealBtnPic);

deal.addActionListener(this);

add(deal);

//stay button

stay =new JButton("Stay", stayBtnPic);

add(stay);

}//end ButtonPanel c'tor

//****************************************************

publicvoid actionPerformed(ActionEvent e)

{

Object o = e.getSource();

if (o == deal)

cp.animateHit("player",1,deck.cards[0]);

}

//****************************************************

}//end class ButtonPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class PanelBextends JPanel

{

private BufferedImage picOfMe;

public PanelB()

{

try

{

picOfMe = ImageIO.read(new File("picofme.JPG"));

}catch(IOException xxx)

{

System.out.println("Missing JPG, terminating..");

System.exit(0);

}

setPreferredSize(new Dimension(200,200));

setBackground(new Color(0, 153, 51));

repaint();

}//end PanelB c'tor

//************************************************************

publicvoid paint(Graphics g)

{

g.drawImage(picOfMe,15,0,null);

}//end paint()

//*************************************************************

}//end PanelB class

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class CardPanelextends JPanel

{

private BufferedImage animationCard =null;

privateint animX = 350;

privateint animY = 200;

private BufferedImage deckPic =null;

private BufferedImage dealerCard1 =null;

private BufferedImage dealerCard2 =null;

private BufferedImage dealerCard3 =null;

private BufferedImage dealerCard4 =null;

private BufferedImage dealerCard5 =null;

private BufferedImage playerCard1 =null;

private BufferedImage playerCard2 =null;

private BufferedImage playerCard3 =null;

private BufferedImage playerCard4 =null;

private BufferedImage playerCard5 =null;

public CardPanel()

{

setPreferredSize(new Dimension(500,600));

try

{

deckPic = ImageIO.read(new File("cards/card_deck.JPG"));

dealerCard1 = ImageIO.read(new File("cards/card_back.JPG"));

animationCard = dealerCard1;

}catch(IOException crap)

{

System.out.println("Missing graphics file, terminating..");

System.exit(0);

}

repaint();

}//end CardPanel c'tor

//**************************************************************

publicvoid paint(Graphics g)

{

//draw animation (wherever it is)

g.drawImage(animationCard,animX,animY,null);

//draw deck

//g.drawImage(deckPic,350,200,null);

//draw dealer cards

g.drawImage(dealerCard1,50,10,null);

g.drawImage(dealerCard2,70,10,null);

g.drawImage(dealerCard3,90,10,null);

g.drawImage(dealerCard4,110,10,null);

g.drawImage(dealerCard5,130,10,null);

//draw user cards example

g.drawImage(playerCard1,50,450,null);

g.drawImage(playerCard2,70,450,null);

g.drawImage(playerCard3,90,450,null);

g.drawImage(playerCard4,110,450,null);

g.drawImage(playerCard5,130,450,null);

System.out.println("Paint running");

}//end paint()

//**************************************************************

publicvoid animateHit(String playerOrDealer,int numCardsInHand,

Card c)

{

if (playerOrDealer =="player")

{

if (numCardsInHand == 1)

{

while (animY != 450)

{

System.out.println("Looping, animY = " + animY);

animY += 2;

try

{

Thread.sleep(50);

}catch(InterruptedException ie)

{

System.exit(0);

}

repaint();

}//end while

}

}//end "player" if

}//end animateHit()

//****************************************************************

}//end class CardPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

}//end BlackjackPanel

If you look in the CardPanel.paint() method, you'll see that I write a line to print out a statement to notify that the paint method is indeed running. Upon execution, the expecting string is only printed once, so I believe that when I call animateHit(), a differen't panel's Paint() method is being called. How can I resolve this? I'll need to call the method from another panel. I've already tried using the this keyword.

[16527 byte] By [kwiknessa] at [2007-11-27 5:44:34]
# 1
can someone please help me with this?
kwiknessa at 2007-7-12 15:25:16 > top of Java-index,Desktop,Core GUI APIs...
# 2

The problem is that you're calling animateHit from within the event dispatch thread. That means that the event dispatch thread is tied up inside the animateHit method and won't do anything else until animateHit terminates. When animateHit calls repaint, it queues up a request to repaint the panel which in turn will call paint. Those queued up requests cannot be honored until animateHit finishes, because all this must occur within the event dispatch thread. At some point, animateHit finally exits and the EDT is free to call your paint() method via repaint. By this time, animY is set to 450 and there is no animation. Also, duplicate requests to repaint are reduced to a single call to repaint since they would just be redundantly redrawing the same picture with no animation, i.e., animY == 450.

You need to kick off animateHit in a different thread. Any time you call Thread.sleep it should be from a thread other than the EDT. Note that actionPerformed() is always called from within the EDT. Maybe you could make actionPreformed start the thread instead of trying to directly animate your card dealing.

Also, you should override paintComponent(), not paint() since JPanel is a swing component.

if you're gonna do this kind of animation, you'll need to become knowledgable about threads.

Message was edited by:

BillKrieger

BillKriegera at 2007-7-12 15:25:16 > top of Java-index,Desktop,Core GUI APIs...
# 3

import java.awt.*;

import java.awt.event.*;

import java.awt.image.BufferedImage;

import java.io.*;

import java.util.*;

import java.util.List;

import javax.imageio.ImageIO;

import javax.swing.*;

public class CardMovingTest {

CardMovingTable cardTable;

public CardMovingTest(BufferedImage[] images) {

cardTable = new CardMovingTable(images);

}

private JPanel getCardTable() {

return cardTable;

}

private JPanel getControls() {

final JButton deal = new JButton("deal");

final JButton newHand = new JButton("new hand");

JPanel panel = new JPanel();

ActionListener l = new ActionListener() {

public void actionPerformed(ActionEvent e) {

JButton button = (JButton)e.getSource();

if(button == deal) {

boolean haveMoreCards = cardTable.animateHit();

if(!haveMoreCards)

button.setEnabled(false);

}

if(button == newHand) {

cardTable.newHand();

if(!deal.isEnabled())

deal.setEnabled(true);

// So you can use the space bar.

deal.requestFocusInWindow();

}

}

};

deal.addActionListener(l);

newHand.addActionListener(l);

panel.add(deal);

panel.add(newHand);

return panel;

}

public static void main(String[] args) throws IOException {

String path = "playingCards/";

BufferedImage[] images = new BufferedImage[52];

for(int j = 0, k = 1; j < images.length; j++, k++)

images[j] = ImageIO.read(new File(path + k + ".jpg"));

CardMovingTest test = new CardMovingTest(images);

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(test.getCardTable());

f.getContentPane().add(test.getControls(), "Last");

f.setSize(400,400);

f.setLocation(200,200);

f.setVisible(true);

}

}

class CardMovingTable extends JPanel implements Runnable {

List<BufferedImage> cardImages;

List<BufferedImage> dealerHand;

Thread thread;

boolean animating = false;

int cardIndex = -1;

int handIndex = -1;

int[] xKey = { 50, 70, 90, 110, 130 };

final int START = 10;

final int END = 175;

int animY = START;

public CardMovingTable(BufferedImage[] images) {

cardImages = new ArrayList<BufferedImage>(Arrays.asList(images));

dealerHand = new ArrayList<BufferedImage>();

reset();

}

protected void paintComponent(Graphics g) {

super.paintComponent(g);

// Draw non-animating dealer cards.

for(int j = 0; j < dealerHand.size(); j++) {

if(animating && j == handIndex)

continue;

int y = j <= handIndex ? END : START;

g.drawImage(dealerHand.get(j), xKey[j], y, this);

}

if(animating && handIndex > -1)

g.drawImage(dealerHand.get(handIndex), xKey[handIndex], animY, null);

}

public boolean animateHit() {

if(!animating) {

handIndex++;

start();

}

return handIndex < dealerHand.size()-1;

}

private void start() {

if(!animating) {

animating = true;

thread = new Thread(this);

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

}

private void stop() {

animating = false;

if(thread != null)

thread.interrupt();

thread = null;

animY = START;

}

public void run() {

while (animating) {

boolean done = moveAhead();

repaint();

if(done)

stop();

try {

Thread.sleep(50);

} catch(InterruptedException ie) {

stop();

}

}

}

private boolean moveAhead() {

animY += 2;

if(animY >= END) {

animY = END;

return true;

}

return false;

}

protected void newHand() {

dealerHand.clear();

for(int j = 0; j < 5; j++) {

cardIndex++;

if(cardIndex > cardImages.size()-1)

cardIndex = 0;

dealerHand.add(cardImages.get(cardIndex));

}

handIndex = -1;

repaint();

}

private void reset() {

shuffle();

newHand();

}

private void shuffle() {

for(int j = 0; j < 6; j++)

Collections.shuffle(cardImages);

}

}

crwooda at 2007-7-12 15:25:16 > top of Java-index,Desktop,Core GUI APIs...
# 4

Thanks guys, I was pretty confident with this project before I started it. I got As in both my Java and Advanced Java classes, but it looks like, once again, experience is the best teacher.

> private void stop() {

>animating = false;

> if(thread != null)

>thread.interrupt();

>thread = null;

>animY = START;

>}

This is a great way to kill a thread. Thank you.

kwiknessa at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...
# 5

Ok, i've patched up my code. I implemented the Thread interface, and coded start(), run(), and stop() methods. My code is still really disorganized at this point, but at the moment i'm just trying to get the animation to work correctly. Here are my results..

http://kouellette16.home.comcast.net/ss.bmp

As you can see, the whole main panel is being repainted to the right. Why is this happening?

Here's the new code:

import javax.swing.JPanel;

import javax.swing.JButton;

import javax.swing.ImageIcon;

import java.awt.Color;

import java.awt.image.BufferedImage;

import java.awt.GridBagLayout;

import java.awt.GridBagConstraints;

import java.awt.FlowLayout;

import java.awt.Insets;

import java.awt.Component;

import java.awt.Graphics;

import java.awt.Dimension;

import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;

import javax.imageio.ImageIO;

import java.io.File;

import java.io.IOException;

public class BlackjackPanel extends JPanel

{

private Deck deck;

private CardPanel cp;

public BlackjackPanel()

{

deck = new Deck();

setLayout(new GridBagLayout());

//dark green

setBackground(new Color(0, 153, 51));

add(new LogoPanel(), getConstraints(0,0,1,1,GridBagConstraints.NORTHWEST));

add(new ButtonPanel(),getConstraints(0,2,1,1,GridBagConstraints.EAST));

cp = new CardPanel();

add(cp,getConstraints(4,0,5,5,GridBagConstraints.CENTER));

add(new PanelB(),getConstraints(9,0,1,1,GridBagConstraints.NORTHEAST));

}//end BlackjackPanel c'tor

//**********************************************************

private GridBagConstraints getConstraints(int gridx,

int gridy, int gridWidth, int gridHeight, int anchor)

{

GridBagConstraints c = new GridBagConstraints();

c.insets = new Insets(5, 5, 5, 5);

c.ipadx = 0;

c.ipady = 0;

c.gridx = gridx;

c.gridy = gridy;

c.gridwidth = gridWidth;

c.gridheight = gridHeight;

c.anchor = anchor;

return c;

}//end getConstraints

//*************************************************************

class LogoPanel extends JPanel

{

private BufferedImage logo;

public LogoPanel()

{

setPreferredSize(new Dimension(250,300));

setBackground(new Color(0, 153, 51));

//logo

try

{

logo = ImageIO.read(new File("logo.JPG"));

}catch(IOException e)

{

System.out.println("logo.JPG is missing. Terminating..");

System.exit(0);

}

repaint();

}//end LogoPanel c'tor

//*****************************************************************

protected void paintComponent(Graphics g)

{

g.drawImage(logo,0,0,null);

}

}//end class LogoPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class ButtonPanel extends JPanel implements ActionListener

{

private ImageIcon dealBtnPic;

private ImageIcon hitBtnPic;

private ImageIcon stayBtnPic;

private ImageIcon splitBtnPic;

private JButton deal;

private JButton hit;

private JButton stay;

private JButton split;

public ButtonPanel()

{

//setBackground(new Color(0, 153, 51));

setBackground(new Color(0,0,0));

setLayout(new GridBagLayout());

setPreferredSize(new Dimension(250, 300));

//load button icons

splitBtnPic = new ImageIcon("splitbtnpic.JPG");

dealBtnPic = new ImageIcon("dealbtnpic.JPG");

hitBtnPic = new ImageIcon("hitbtnpic.JPG");

stayBtnPic = new ImageIcon("staybtnpic.JPG");

//split button

split = new JButton("Split", splitBtnPic);

add(split);

//hit button

hit = new JButton("Hit", hitBtnPic);

add(hit);

//deal button

deal = new JButton("Deal", dealBtnPic);

deal.addActionListener(this);

add(deal);

//stay button

stay = new JButton("Stay", stayBtnPic);

add(stay);

}//end ButtonPanel c'tor

//****************************************************

public void actionPerformed(ActionEvent e)

{

Object o = e.getSource();

if (o == deal)

cp.start();

}

//****************************************************

}//end class ButtonPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class PanelB extends JPanel

{

private BufferedImage picOfMe;

public PanelB()

{

try

{

picOfMe = ImageIO.read(new File("picofme.JPG"));

}catch(IOException xxx)

{

System.out.println("Missing JPG, terminating..");

System.exit(0);

}

setPreferredSize(new Dimension(200,200));

setBackground(new Color(0, 153, 51));

repaint();

}//end PanelB c'tor

//************************************************************

public void paint(Graphics g)

{

g.drawImage(picOfMe,15,0,null);

}//end paint()

//*************************************************************

}//end PanelB class

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

class CardPanel extends JPanel implements Runnable

{

private BufferedImage animationCard = null;

private int animX = 350;

private int animY = 200;

//take care of this some other way

private String animateTo = "player";

private int numCardsInHand = 1;

private BufferedImage deckPic = null;

private BufferedImage dealerCard1 = null;

private BufferedImage dealerCard2 = null;

private BufferedImage dealerCard3 = null;

private BufferedImage dealerCard4 = null;

private BufferedImage dealerCard5 = null;

private BufferedImage playerCard1 = null;

private BufferedImage playerCard2 = null;

private BufferedImage playerCard3 = null;

private BufferedImage playerCard4 = null;

private BufferedImage playerCard5 = null;

Thread thread;

public CardPanel()

{

setPreferredSize(new Dimension(500,600));

try

{

deckPic = ImageIO.read(new File("cards/card_deck.JPG"));

dealerCard1 = ImageIO.read(new File("cards/card_back.JPG"));

animationCard = dealerCard1;

}catch(IOException crap)

{

System.out.println("Missing graphics file, terminating..");

System.exit(0);

}

repaint();

}//end CardPanel c'tor

//**************************************************************

private void start()

{

thread = new Thread(this);

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

//**************************************************************

public void run()

{

if (animateTo == "player")

{

if (numCardsInHand == 1)

{

while (animY != 450)

{

System.out.println("Looping, animY = " + animY);

animY += 2;

try

{

Thread.sleep(5);

}catch(InterruptedException ie)

{

System.exit(0);

}

repaint();

}//end while

}

}//end "player" if

}

//**************************************************************

private void stop()

{

if (thread != null)

{

thread.interrupt();

thread = null;

}

}

//**************************************************************

public void paint(Graphics g)

{

//draw animation (wherever it is)

g.drawImage(animationCard,animX,animY,null);

//draw deck

//g.drawImage(deckPic,350,200,null);

//draw dealer cards

g.drawImage(dealerCard1,50,10,null);

g.drawImage(dealerCard2,70,10,null);

g.drawImage(dealerCard3,90,10,null);

g.drawImage(dealerCard4,110,10,null);

g.drawImage(dealerCard5,130,10,null);

//draw user cards example

g.drawImage(playerCard1,50,450,null);

g.drawImage(playerCard2,70,450,null);

g.drawImage(playerCard3,90,450,null);

g.drawImage(playerCard4,110,450,null);

g.drawImage(playerCard5,130,450,null);

System.out.println("Paint running");

}//end paint()

//**************************************************************

/*public void animateHit(String playerOrDealer, int numCardsInHand,

Card c)

{

if (playerOrDealer == "player")

{

if (numCardsInHand == 1)

{

while (animY != 450)

{

System.out.println("Looping, animY = " + animY);

animY += 2;

try

{

Thread.sleep(50);

}catch(InterruptedException ie)

{

System.exit(0);

}

repaint();

}//end while

}

}//end "player" if

}//end animateHit()*/

//****************************************************************

}//end class CardPanel

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

}//end BlackjackPanel

kwiknessa at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...
# 6
Anyone?
kwiknessa at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...
# 7
why are you overriding paint when you are using swing? shouldn't you be overriding paintcomponent?
petes1234a at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...
# 8
sorry that wasn't the most recent version of my source, the only difference between what i have there and now is that i changed the paint method decs to protected void paintComponent(Graphics g)
kwiknessa at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...
# 9
solved by making the call: super.paintComponent(Graphics g)
kwiknessa at 2007-7-12 15:25:17 > top of Java-index,Desktop,Core GUI APIs...