Using a thread and need to use invokeLater

  • (2 Pages)
  • +
  • 1
  • 2

21 Replies - 868 Views - Last Post: 07 March 2012 - 10:47 AM Rate Topic: -----

#1 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Using a thread and need to use invokeLater

Posted 06 March 2012 - 01:46 PM

I am creating a memory card game. So far, the pictures turn face up once the user clicks on them. My problem is that when I click on the second picture, the picture never gets shown and both cards flip back over. I am using a thread sleep method, which I am trying to use the invokeLater method. I want to be able to have both cards flip over after the user clicks on two of them and then wait 2 seconds and flip back over if these are not matches. Here is my code for the thread part. What I have kind of works code wise, but there is an error on the waitAndSeethread.start() method. The error is waitAndSeethread() cannot be resolved. Thanks for your help.

private class cardActionListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e){
			if(card1 == null){
				card1 = (Card) e.getSource();
				card1.flipCardFace();
			}
			else{
				card2 = (Card) e.getSource();
				card2.flipCardFace();
				attempts++;
				if(card1.equals(card2)){
					matches++;
				}
				else{
					SwingUtilities.invokeLater(new Runnable(){
						public void run(){
							Thread waitAndSeethread = new Thread(){
								public void run() {
									try{
										Thread.sleep(2000);
									}
									catch(Exception ex){
										ex.printStackTrace();
									}
									//check if the cards are face up and flip then down if not.							
								}
							};
						};
					});
					waitAndSeethread.start();
				}
				card1.flipCardBack();
				card2.flipCardBack();
				card1 = null;
				card2 = null;
			}	
	}



Is This A Good Question/Topic? 0
  • +

Replies To: Using a thread and need to use invokeLater

#2 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 06 March 2012 - 01:55 PM

Can we see how you're doing the flipping?
Was This Post Helpful? 0
  • +
  • -

#3 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 06 March 2012 - 01:59 PM

Yes, the flipping is done in my Card class...

public class Card extends JButton implements ActionListener{
	private String symbol = "";
	private int num;
	private boolean face = false;
	private int row;
	private int column;
	private ImageIcon faceIcon;
	private ImageIcon backIcon;
	private Card match;
	
	//Card constructor
	public Card(String symbol){
		this.symbol = symbol;
		this.setActionCommand("click");
		java.net.URL image = Memory.class.getResource("phillies.jpg");
		java.net.URL front = Memory.class.getResource(symbol);
		backIcon = new ImageIcon(image);
		faceIcon = new ImageIcon(front);
		this.setIcon(backIcon);
		this.addActionListener(this);
	}
	
	public void flipCardBack(){
		this.setIcon(backIcon);
	}
	
	public void flipCardFace(){
		this.setIcon(faceIcon);
	}
	
	public boolean equals(Card potMatch){
		return(potMatch.getSymbol().equals(this.getSymbol()));
	}
	
	public void setMatch(Card sMatch){
		match = sMatch;
	}


Was This Post Helpful? 0
  • +
  • -

#4 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 06 March 2012 - 02:10 PM

Quote

SwingUtilities.invokeLater


Instead of the above it will be cleaner if you do

new Flipper().execute();


with

    private class Flipper extends SwingWorker<Void, Void> {
        public Void doInBackground() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                /* ignore */
            }
	    return null;
        }

        public void done() {
            // Flip it here
        }
    }


This post has been edited by g00se: 06 March 2012 - 02:11 PM

Was This Post Helpful? 0
  • +
  • -

#5 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 06 March 2012 - 02:16 PM

Do I still need the ActionListener I used in my first post then? Would this all go in the done() function?
Was This Post Helpful? 0
  • +
  • -

#6 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 06 March 2012 - 02:21 PM

If all it's doing is the flipping, then you probably don't need it, no
Was This Post Helpful? 0
  • +
  • -

#7 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 08:48 AM

Is there any way to do this by using the code I was trying to? I don't want to make another private class because then I have to fix a bunch of stuff in my code.
Was This Post Helpful? 0
  • +
  • -

#8 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 08:53 AM

I think there's some confusion here. That code only needs to be called when a card is flipped. It should require hardly any changing of your code

btw you should only need one method for flipping - it's a boolean state that only needs to be toggled

This post has been edited by g00se: 07 March 2012 - 08:57 AM

Was This Post Helpful? 0
  • +
  • -

#9 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 09:00 AM

OK here's what I did, it still doesn't work. When I click on the second card, it waits 2 seconds and then flips them both back over, without ever showing the 2nd card.

private class cardActionListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e){
			if(card1 == null){
				card1 = (Card) e.getSource();
				card1.flipCardFace();
			}
			else{
				card2 = (Card) e.getSource();
				card2.flipCardFace();
				matchAttempts++;
				if(card1.equals(card2)){
					matches++;
				}
				else{
					Flipper flipCards = new Flipper();
					flipCards.doInBackground();
					flipCards.done();
				}
				card1 = null;
				card2 = null;
			}	
		}
	}
	
	private class Flipper extends SwingWorker<Void, Void>{
		public Void doInBackground(){
			try{
				Thread.sleep(2000);
			}
			catch(InterruptedException e){
				e.printStackTrace();
			}
			return null;
		}
		
		public void done(){
			card1.flipCardBack();
			card2.flipCardBack();
		}
	}


Was This Post Helpful? 0
  • +
  • -

#10 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 09:16 AM

Quote

Flipper flipCards = new Flipper();
flipCards.doInBackground();
flipCards.done();


No, that's not how you use it. All you do it call execute. The code that implements the actual flipping should be in done()
Was This Post Helpful? 0
  • +
  • -

#11 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 09:22 AM

Thanks, it works now! Except once I click on the 2nd card, which flips, an error message comes up about a null pointer in the line card1.flipCardBack(); Should I post all my code? For some reason, it's also not understanding what the matches are, even though that was working yesterday and I haven't touched it.
Was This Post Helpful? 0
  • +
  • -

#12 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 09:25 AM

Post the full stack trace AND the code please
Was This Post Helpful? 0
  • +
  • -

#13 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 09:33 AM

The matching is done in the Card class, here is the error..

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Layout$Flipper.done(Layout.java:113)
at javax.swing.SwingWorker$5.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unknown Source)
at sun.swing.AccumulativeRunnable.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

This is my main class
import java.awt.event.*;

public class Memory implements ActionListener{
	Layout test = new Layout();
	public Memory(){
		test.jpanel();
	}
}



This is my Card class
import java.awt.event.*;
import javax.swing.*; 

public class Card extends JButton implements ActionListener{
	private String symbol = "";
	private int num;
	private boolean face = false;
	private int row;
	private int column;
	private ImageIcon faceIcon;
	private ImageIcon backIcon;
	private Card match;
	
	//Card constructor
	public Card(String symbol){
		this.symbol = symbol;
		this.setActionCommand("click");
		java.net.URL image = Memory.class.getResource("phillies.jpg");
		java.net.URL front = Memory.class.getResource(symbol);
		backIcon = new ImageIcon(image);
		faceIcon = new ImageIcon(front);
		this.setIcon(backIcon);
		this.addActionListener(this);
	}
	
	public void flipCardBack(){
		this.setIcon(backIcon);
	}
	
	public void flipCardFace(){
		this.setIcon(faceIcon);
	}
	
	public boolean equals(Card potMatch){
		return(potMatch.getSymbol().equals(this.getSymbol()));
	}
	
	public void setMatch(Card sMatch){
		match = sMatch;
	}
	
	/*@Override
	public void actionPerformed(ActionEvent event) {
		
	}*/
	
	public String getSymbol(){
		return symbol;
	}
	
	public void setSymbol(String text){
		this.symbol = text;
	}
	
	public int getNum(){
		return num;
	}
	
	public void setNum(int number){
		this.num = number;
	}
	
	public boolean getFace(){
		return face;
	}
	
	public void setFace(boolean f){
		this.face = f;
	}
	
	public int getRow(){
		return row;
	}
	
	public void setRow(int row){
		this.row = row;
	}

	public int getColumn(){
		return column;
	}	

	public void setColumn(int column){
		this.column = column;
	}
}



Layout class
import java.util.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class Layout extends JButton implements ActionListener{
	
	ArrayList<Card> cardList;
	String[] imageNames = {"blanton.jpg", "brown.jpg", "halladay.jpg", "hamels.jpg", "howard.jpg", "lee.jpg", "mayberry.jpg", "papelbon.jpg", "pence.jpg",
			"polanco.jpg", "rollins.jpg", "ruiz.jpg", "utley.jpg", "victorino.jpg", "worley.jpg"};
	ArrayList<ImageIcon> images = new ArrayList<ImageIcon>();
	
	private Card card1 = null;
	private Card card2 = null;
	private int matches = 0;
	private int matchAttempts = 0;
	
	public void jpanel(){
		createCardList();
		cardActionListener cardAction = new cardActionListener();
		addsListener(cardAction);
		JFrame frame = new JFrame();
		JPanel gridPanel = new JPanel(new GridLayout(5, 6));
		JPanel northPanel = new JPanel();
		
		JLabel attempts = new JLabel("Attempts: " + matchAttempts);
		JButton playAgain = new JButton("Play Again");
		JLabel match = new JLabel("Matches: " + matches);
		northPanel.add(attempts);
		northPanel.add(match);
		northPanel.add(playAgain);
		frame.setSize(900, 700);
		frame.add(northPanel, BorderLayout.NORTH);
		northPanel.setSize(900, 100);
		frame.add(gridPanel);
		gridPanel.setSize(800, 600);
		for(int i=0; i<cardList.size(); i++){
				gridPanel.add(cardList.get(i));
		}	
		
		for(int i=0; i<imageNames.length; i++){
			images.add(new ImageIcon(imageNames[i]));
		}
		
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		if(playAgain.equals("click")){
			this.jpanel();
		}
	}
	
	public void createCardList(){
		cardList = new ArrayList<Card>();
		for(int i=0; i<15; i++){
			String image1 = imageNames[i];
			cardList.add(new Card(image1));
			cardList.add(new Card(image1));		
		}
		Collections.shuffle(cardList);
	}
	
	@Override
	public void actionPerformed(ActionEvent event) {
		// show image on button that was clicked
		//JButton b = (JButton)event.getSource();
		//System.out.print(event.getActionCommand());	
	}
	
	
	private class cardActionListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e){
			if(card1 == null){
				card1 = (Card) e.getSource();
				card1.flipCardFace();
			}
			else{
				card2 = (Card) e.getSource();
				card2.flipCardFace();
				matchAttempts++;
				if(card1.equals(card2)){
					matches++;
				}
				else{
					Flipper flipCards = new Flipper();
					flipCards.execute();
				}
				card1 = null;
				card2 = null;
			}	
		}
	}
	
	private class Flipper extends SwingWorker<Void, Void>{
		public Void doInBackground(){
			try{
				Thread.sleep(2000);
			}
			catch(InterruptedException e){
				e.printStackTrace();
			}
			return null;
		}
		
		public void done(){
			card1.flipCardBack();
			card2.flipCardBack();
		}
	}
	
	public void addsListener(cardActionListener cardAction){
		int i = 0;
		while(i<cardList.size()){
			cardList.get(i).addActionListener(cardAction);
			i++;
		}
	}
	public int getMatches(){
		return matches;
	}
	
	public void setMatches(int matches){
		this.matches = matches;
	}
	
	public int getMatchAttempts(){
		return matchAttempts;
	}
	
	public void setAttempts(int attempts){
		this.matchAttempts = attempts;
	}
}


Was This Post Helpful? 0
  • +
  • -

#14 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2657
  • View blog
  • Posts: 11,208
  • Joined: 20-September 08

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 10:04 AM

Quote

at Layout$Flipper.done(Layout.java:113)


Something not initialized in done() at lines 113
Was This Post Helpful? 0
  • +
  • -

#15 ral106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 02-August 11

Re: Using a thread and need to use invokeLater

Posted 07 March 2012 - 10:07 AM

Ok I fixed that, I was setting both cards back to null before flipping them back over. Now it partly works. After the two cards are flipped over, while waiting the 2 seconds, it allows you to click a third card and that flips over, how can I make it so that you can only flip 2 cards over?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2