Threads Thread.Sleep Problem im Zusammenhang mit GUI/ActionPerformed-Methode

  • Themenstarter Themenstarter MichaelAnfänger
  • Beginndatum Beginndatum
M

MichaelAnfänger

Gast
Hi,

wir sollen in unserem Semester ein Memory-Spiel programmieren, und sind dabei auf ein Problem gestoßen, das wir auch nach mehreren Stunden nicht lösen konnten. Ehrlich gesagt, habe ich das selbe Problem schon mehrfach hier im Forum gefunden, es aber nicht geschafft, die angebotenen Lösungen zu verstehen, bzw. umzusetzen. Es geht darum, dass, nachdem zwei nicht zusammengehörende Karten geöffnet wurden, diese nach einer kurzen Wartezeit wieder zugedeckt werden. Auftretendes Problem ist halt, dass die letzte der beiden geöffneten Karten erst garnicht angezeigt wird, da beide schon vorher wieder zugedeckt werden. Ich habe hier mal, die wie ich denke, relevanten Code-Teile hinzugefügt. Die Memory-Karten sind auf Buttons angezeigte Icons, die actionPerformed-methode gehört daher ebenfalls zu diesen Buttons:

Java:
	public void pause()
	{
		try
		{
			Thread.sleep(5000);
		}
		catch (Exception e)
		{
			
		}
	}

	public void setCardBlind()
	{
		buttonCardOne.setIcon(ico);
		buttonCardTwo.setIcon(ico);
	}

private class SwingAction_3 extends AbstractAction {
		public SwingAction_3() {
			putValue(NAME, "");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) 
		{
			setActiveElement(e);
			allCards.get(activeElement).setOpened(true);
			
			ImageIcon ico = new ImageIcon(allCards.get(activeElement).getPath());
			ico.setImage(ico.getImage().getScaledInstance(100,100,Image.SCALE_DEFAULT)); 
			
			((AbstractButton) e.getSource()).setIcon(ico);
					
			if (alreadyClicked == false)
			{
				CardOne = allCards.get(activeElement);
				buttonCardOne = (JButton) e.getSource();
				alreadyClicked = true;
			}
			else
			{
				CardTwo = allCards.get(activeElement);
				buttonCardTwo = (JButton) e.getSource();
				alreadyClicked = false;
				
				if (CardOne.getID() == CardTwo.getIdenticCardID())
				{
					currPlayer.setPoints(1);
					lbl2.setText("Punktzahl: " + String.valueOf(currPlayer.getPoints()));
					CardOne.setOpened(true);
					CardTwo.setOpened(true);	
				}
				else
				{
					currPlayer = currPlayer.getFollowingPlayer();
					lbl1.setText("Aktueller Spieler: " + String.valueOf(currPlayer.getID()));
					lbl2.setText("Punktzahl: " + String.valueOf(currPlayer.getPoints()));
					CardOne.setOpened(false);
					CardTwo.setOpened(false);
pause();
					setCardBlind();
				}
			}
		}

Ich hoffe das ist halbwegs übersichtlich und das mir das jemand für totale Anfänger erklären kann.

Freundliche Grüße
Michael
 
Der gesamte Code sähe so aus, da sieht man auch wo pause() genau liegt, falls es das ist was du meinsest:

Java:
public class Memory{

	private JFrame frame;
	private final Action pushStart = new SwingAction();
	private final Action setPlayer1 = new SwingAction_1();
	private final Action setPlayer2 = new SwingAction_2();
	JButton btn1;
	JButton btn2;
	JButton btn3;
	JButton btn4;
	JLabel lbl1;
	JLabel lbl2;
	int numberOfPlayers = 1;
	Card c = new Card();
	Player pl1;
	Player pl2;
	Player currPlayer;
	Card CardOne = null;
	Card CardTwo = null;
	JButton buttonCardOne;
	JButton buttonCardTwo;
	ImageIcon ico;
	ArrayList<Card> allCards = new ArrayList<Card>();
	boolean alreadyClicked = false;
	int activeElement;
	private final Action action = new SwingAction_3();
	private static boolean istPause = false;


	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Memory window = new Memory();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public Memory() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setResizable(false);
		frame.setBounds(100, 100, 915, 552);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);
		
		JMenu mnDatei = new JMenu("Datei");
		menuBar.add(mnDatei);
		
		JMenuItem mntmSpielBeginnen = new JMenuItem("Spiel beginnen");
		mntmSpielBeginnen.setAction(pushStart);
		mnDatei.add(mntmSpielBeginnen);
		
		JMenu mnAnzahlSpieler = new JMenu("Anzahl Spieler");
		mnDatei.add(mnAnzahlSpieler);
		
		JMenuItem mntmSpieler = new JMenuItem("1 Spieler");
		mntmSpieler.setAction(setPlayer1);
		mnAnzahlSpieler.add(mntmSpieler);
		
		JMenuItem mntmSpieler_1 = new JMenuItem("2 Spieler");
		mntmSpieler_1.setAction(setPlayer2);
		mnAnzahlSpieler.add(mntmSpieler_1);
		
		JMenu mnHilfe = new JMenu("Hilfe");
		menuBar.add(mnHilfe);
		frame.getContentPane().setLayout(null);
		
		btn1 = new JButton("");
		btn1.setAction(action);
		
		btn1.setBounds(10, 11, 100, 100);
		frame.getContentPane().add(btn1);
		
		btn2 = new JButton("");
		btn2.setAction(action);
		btn2.setBounds(120, 11, 100, 100);
		frame.getContentPane().add(btn2);
		
		btn3 = new JButton("");
		btn3.setAction(action);
		btn3.setBounds(230, 11, 100, 100);
		frame.getContentPane().add(btn3);
		
		btn4 = new JButton("");
		btn4.setAction(action);
		btn4.setBounds(340, 11, 100, 100);
		frame.getContentPane().add(btn4);
		
		lbl1 = new JLabel("Aktueller Spieler: 1");
		lbl1.setBounds(10, 478, 116, 14);
		frame.getContentPane().add(lbl1);
		
		lbl2 = new JLabel("Punktzahl: 0");
		lbl2.setBounds(136, 478, 85, 14);
		frame.getContentPane().add(lbl2);
		
		setVisiblity(false);
	}
	
	public void setActiveElement(ActionEvent evt)
	{
		if (evt.getSource() == btn1)
		{
			activeElement = 0;
		}
		else if (evt.getSource() == btn2)
		{
			activeElement = 1;
		}
		else if (evt.getSource() == btn3)
		{
			activeElement = 2;
		}
		else if (evt.getSource() == btn4)
		{
			activeElement = 3;
		}
	}
	
	
	// Setzen der Sichtbarkeit der Buttons
	public void setVisiblity(boolean visible)
	{
		btn1.setVisible(visible);
		btn2.setVisible(visible);
		btn3.setVisible(visible);
		btn4.setVisible(visible);
		lbl1.setVisible(visible);
		lbl2.setVisible(visible);
	}
	
	public void initiateGame(int Players)
	{
		createPlayers(Players);
		createCards();
	}
	
	public void createPlayers(int Players)
	{
		switch (Players)
		{
		case 1:
			pl1 = new Player(1);
			pl1.setFollowingPlayer(pl1);
			break;
		case 2:
			pl1 = new Player(1);
			pl2 = new Player(2);
			pl1.setFollowingPlayer(pl2);
			pl2.setFollowingPlayer(pl1);
			break;
		}
		currPlayer = pl1;
	}
	
	public void createCards()
	{
		allCards.clear();
		
		Card cd1 = new Card(1, "C:\\Jellyfish.jpg", 2);
		Card cd2 = new Card(2, "C:\\Jellyfish.jpg", 1);
		Card cd3 = new Card(3, "C:\\Desert.jpg", 4);
		Card cd4 = new Card(4, "C:\\Desert.jpg", 3);
		
		allCards.add(cd1);
		allCards.add(cd2);
		allCards.add(cd3);
		allCards.add(cd4);
		
		Collections.shuffle(allCards);
	}
	
	public void setStartingImage()
	{
		//Card c = new Card();
		ico = new ImageIcon("C:\\Chrysanthemum.jpg");
		ico.setImage(ico.getImage().getScaledInstance(100,100,Image.SCALE_DEFAULT)); 
		
		btn1.setIcon(ico);
		btn2.setIcon(ico);
		btn3.setIcon(ico);
		btn4.setIcon(ico);
	}
	
	public void setCardBlind()
	{
		buttonCardOne.setIcon(ico);
		buttonCardTwo.setIcon(ico);
	}
	
	public void pause()
	{
		try
		{
			Thread.sleep(5000);
		}
		catch (Exception e)
		{
			
		}
	}
	
	
	private class SwingAction extends AbstractAction {
		public SwingAction() {
			putValue(NAME, "Spiel beginnen");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) 
		{
			activeElement = 0;
			setStartingImage();
			setVisiblity(true);
			initiateGame(numberOfPlayers);
		}
	}
	
	private class SwingAction_1 extends AbstractAction {
		public SwingAction_1() {
			putValue(NAME, "1 Spieler");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) 
		{
			numberOfPlayers = 1;
		}
	}
	
	private class SwingAction_2 extends AbstractAction {
		public SwingAction_2() {
			putValue(NAME, "2 Spieler");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) 
		{
			numberOfPlayers = 2;
		}
	}
	
	private class SwingAction_3 extends AbstractAction {
		public SwingAction_3() {
			putValue(NAME, "");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) 
		{
			setActiveElement(e);
			allCards.get(activeElement).setOpened(true);
			
			ImageIcon ico = new ImageIcon(allCards.get(activeElement).getPath());
			ico.setImage(ico.getImage().getScaledInstance(100,100,Image.SCALE_DEFAULT)); 
			
			((AbstractButton) e.getSource()).setIcon(ico);
					
			if (alreadyClicked == false)
			{
				CardOne = allCards.get(activeElement);
				buttonCardOne = (JButton) e.getSource();
				alreadyClicked = true;
			}
			else
			{
				CardTwo = allCards.get(activeElement);
				buttonCardTwo = (JButton) e.getSource();
				alreadyClicked = false;
				
				if (CardOne.getID() == CardTwo.getIdenticCardID())
				{
					currPlayer.setPoints(1);
					lbl2.setText("Punktzahl: " + String.valueOf(currPlayer.getPoints()));
					CardOne.setOpened(true);
					CardTwo.setOpened(true);	
				}
				else
				{
					currPlayer = currPlayer.getFollowingPlayer();
					lbl1.setText("Aktueller Spieler: " + String.valueOf(currPlayer.getID()));
					lbl2.setText("Punktzahl: " + String.valueOf(currPlayer.getPoints()));
					CardOne.setOpened(false);
					CardTwo.setOpened(false);
					setCardBlind();
				}
			}
		}
	}
}

Ja, die GUI wird mehr oder weniger blockiert, zumindest wird der Code nicht so abgearbeitet, wie ich das erwarten würde. Hat was mit den Threads zu tun, so viel hab ich noch verstanden, da läuft wohl noch einer automatisch im Hintergrund, der da in die Quere kommt, und zum Problem führt.
 
naja soweit ich weiß läuft awt events über eine queue

also es gibt einen prozess der die ganzen events abarbeitet
wenn du nun einen große arbeit in das event packst, kann sich der prozess nicht mehr um die anderen events kümmern
-> in deinem fall wäre die große arbeit der pause prozess

um das problem zu umgehen sollte man größere arbeiten in einem externen thread laufen lassen.



Das ganze mal in einem Beispiel.

10 Menschen stehen vor einer Tür in einer Warteschlange.
Die Warteschlange wäre in java die EventQueue
So nun ist der nächste Mensch dran, welcher aber sehr übergewichtig ist.
Nun blockiert er die ganzen anderen Menschen die noch in der Warteschlange stehen.

Um das Problem zu lösen eröffnest du einfach eine 2te Tür und schickst den Blocker durch die andere Tür.


Steht auch in "JAva ist auch eine Insel"
Galileo Computing :: Java ist auch eine Insel – 19.26 AWT, Swing und die Threads
punkt 19.26

Das wars eigentlich

mfg
 
Zuletzt bearbeitet:
Danke für die Hilfe, wir haben es jetzt lösen können.

Freundliche Grüße

Michael Behnke
 

Zurück
Oben