Ajuda com Threads

Ola’ pessoal,

Boa noite a todos...
Estou desenvolvendo uma aplicacao como exercicio para a faculdade, e nele tenho um jFrame que inicializa uma Thread... e' um joguinho basico, onde vai aparecer uma bola que desce pela tela e dentro dessa bola tem uma letra, o usuario devera' teclar a letra que esta na bola, acertando sera' computado um valor de pontuacao, errando, sera' computado um erro... neste dois casos, a Thread que movimenta a bola sera' finalizada e inicializada uma nova jogada com a bola surgindo em outra posicao da tela e com uma nova letra e com a velocidade incrementada... ate esta parte esta tudo funcionando de acordo com o esperado... no entanto... se o usuario demorar para digitar a letra da bola e a bola acabar chegando ao final da tela, tem que ser computado um erro e iniciar uma nova jogada... neste ponto nao consegui seguir, a bola para no final da tela, mas nao consigo monitorar que isso aconteceu, entao ela permanece estatica ate que eu digite uma letra certa ou errada onde o sistema inicia uma nova jogada.

A duvida e’, como de dentro do jFrame eu consigo monitorar que a Thread que movimenta a bolinha parou?

Segue o codigo do jFrame:

package br.edu.fcsl.gui;

import java.awt.BorderLayout;

public class AnimacaoFrame extends JFrame implements ActionListener, KeyListener {
	private static final long serialVersionUID = 3777878588823886936L;
	private JPanel contentPane;
	private JSplitPane splitPane;
	private JPanel painelDireito;
	private JPanel painelEsquerdo;
	private JPanel painelEsquerdoInterno;
	private JLabel lblPontuacao;
	private JTextField txfPontuacao;
	private JLabel lblErros;
	private JTextField txfErros;
	private JButton btnIniciar;
	private String letras = "ABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789";
	private char letraAtual;
	private char letraAnterior;
	private JButton btnParar;
	private int erro = 0;
	private int ponto = 0;
	private int velocidade = 0;
	private boolean jogoIniciado = false;
	private JButton btnEncerrar;
	private MovimentoThread tMovimento;

	public static void main(String[] args) {

	public AnimacaoFrame() {
	
	public char sorteiaLetra() {
	
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == btnEncerrar) {
			do_btnEncerrar_actionPerformed(arg0);
		}
		if (arg0.getSource() == btnParar) {
			do_btnNewButton_actionPerformed(arg0);
		}
		if (arg0.getSource() == btnIniciar) {
			do_btnIniciar_actionPerformed(arg0);
		}
	}
	
	protected void do_btnIniciar_actionPerformed(ActionEvent arg0) {
		if (!jogoIniciado) {
			painelDireito.requestFocus();
			erro = 0;
			ponto = 0;
			velocidade = 20;
			jogoIniciado = true;
			statusBotoes();
			iniciarJogo();			
		}
	}
	
	public void iniciarJogo() {	
		limparTela();
		
		txfPontuacao.setText(String.valueOf(ponto));
		txfErros.setText(String.valueOf(erro));
		
		OvalButton bola = new OvalButton(sorteiaLetra());
		
		int x = (int) (Math.random() * (painelDireito.getSize().height - bola.getSize().height));
		int y = 0;
		
		bola.setLocation(x, y);
		painelDireito.add(bola);
		
		tMovimento = new MovimentoThread(bola, velocidade);
		tMovimento.start();
	}
	
	public void limparTela() {
		painelDireito.removeAll();
		painelDireito.repaint();		
	}
	
	protected void do_btnNewButton_actionPerformed(ActionEvent arg0) {
		limparTela();
		JOptionPane.showMessageDialog(this, "Encerrado pelo usuário...", "Final de Jogo", JOptionPane.INFORMATION_MESSAGE);
		jogoIniciado = false;
		statusBotoes();
	}
	public void keyPressed(KeyEvent kp) {
		if (kp.getSource() == painelDireito) {
			do_painelDireito_keyPressed(kp);
		}
	}
	public void keyReleased(KeyEvent kp) {
	}
	public void keyTyped(KeyEvent kp) {
	}
	
	protected void do_painelDireito_keyPressed(KeyEvent kp) {
		if (kp.getKeyChar() == letraAtual) {
			ponto+=100;
			txfPontuacao.setText(String.valueOf(ponto));
			tMovimento.setExecutar(false);
			if (velocidade > 0 ) {
				velocidade -= 1;
			}
			iniciarJogo();
		}
		else {
			erro++;
			if (erro <= 5) {
				txfErros.setText(String.valueOf(erro));
				tMovimento.setExecutar(false);
				iniciarJogo();
			}
			else {
				tMovimento.setExecutar(false);
				limparTela();
				JOptionPane.showMessageDialog(this, "Você perdeu...\nAtingiu mais de 5 erros...", "Final de Jogo", JOptionPane.INFORMATION_MESSAGE);
				jogoIniciado = false;
				statusBotoes();
			}
		}
	}
	
	public void statusBotoes() {
		if (jogoIniciado) {
			btnIniciar.setEnabled(false);
			btnParar.setEnabled(true);
			btnEncerrar.setEnabled(false);
		}
		else {
			btnIniciar.setEnabled(true);
			btnParar.setEnabled(false);
			btnEncerrar.setEnabled(true);			
		}
	}
	protected void do_btnEncerrar_actionPerformed(ActionEvent arg0) {
		if (!jogoIniciado) {
			if (JOptionPane.showConfirmDialog(this, "Deseja realmente encerrar o sistema?", "Encerrar", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
				this.dispose();
			}
		}
	}
}

Segue o codigo da Thread;

package br.edu.fcsl.thread;

import br.edu.fcsl.componente.OvalButton;

public class MovimentoThread extends Thread {
	private OvalButton bola;
	private int velocidade;
	private boolean executar = true;

	public boolean isExecutar() {
		return executar;
	}

	public void setExecutar(boolean executar) {
		this.executar = executar;
	}

	public MovimentoThread(OvalButton bola, int velocidade) {
		this.bola = bola;
		this.velocidade = velocidade;
	}
	
	@Override
	public void run() {
		int x = bola.getLocation().x;
		int y = bola.getLocation().y;
		int tamanhoTotal = bola.getParent().getSize().height - bola.getSize().height;
		
		while (executar) {
			y++;
			if (y >= tamanhoTotal) {
				executar = false;
			}
			bola.setLocation(x, y);
			try {
				sleep(velocidade);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

Desde ja agradeco a quem puder ajudar, e peco desculpas se o topico estiver extenso, e’ a primeira vez que estou postanto, ainda nao estou muito familiarizado.

Se tivesse o código da OvalButton ficaria mais fácil de testar. Uma solução que vi de imediato seria você passar no construtor da Thread o objeto da AnimacaoFrame, assim a thread poderia interferir na view (AnimacaoFrame) e modifica-la quando o “y” da bolinha ultrapassasse o limite da tela.

[code]package br.edu.fcsl.thread;

import br.edu.fcsl.componente.OvalButton;

public class MovimentoThread extends Thread {
private OvalButton bola;
private int velocidade;
private boolean executar = true;
private AnimacaoFrame frame;

public boolean isExecutar() {
	return executar;
}

public void setExecutar(boolean executar) {
	this.executar = executar;
}

    // AQUI!!! Adiciona o objeto da AnimacaoFrame
public MovimentoThread(OvalButton bola, int velocidade, AnimacaoFrame frame) {
	this.bola = bola;
	this.velocidade = velocidade;
            this.frame = frame;
}

@Override
public void run() {
	int x = bola.getLocation().x;
	int y = bola.getLocation().y;
	int tamanhoTotal = bola.getParent().getSize().height - bola.getSize().height;
	
	while (executar) {
		y++;
		if (y >= tamanhoTotal) {
			executar = false;
                            //AQUI! Incremente a erro e chame o metodo iniciarJogo(), ambos do objeto da AnimacaoFrame
                            this.frame.erro++;
                            this.frame.iniciarJogo();
		}
		bola.setLocation(x, y);
		try {
			sleep(velocidade);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

}
[/code]

Para isso, é preciso deixar a variavel “erro” com publica na AnimacaoFrame e na hora de chamar a MovimentaThread, faça assim:

tMovimento = new MovimentoThread(bola, velocidade, this); tMovimento.start();

Bom dia a todos…

Obrigado "gqferreira", vou implementar da forma como você sugeriu e depois posto o resultado.

Segue o código da OvalButton:

package br.edu.fcsl.componente;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JButton;

public class OvalButton extends JButton {
	private static final long serialVersionUID = -4267256135753453602L;
	private char letra;

	public OvalButton(char letra) {
		setContentAreaFilled(false);
		setFont(new Font("arial", Font.BOLD, 14));
		setText(String.valueOf(letra));
		setSize(50, 50);
		setPreferredSize(new Dimension(50, 50));
		setBackground(Color.blue);
		setForeground(Color.white);
		setFocusable(false);
	}

	@Override
	protected void paintBorder(Graphics g) {
		g.setColor(getForeground());
		g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
	}

	@Override
	protected void paintComponent(Graphics g) {
		g.setColor(getBackground());
		g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
		super.paintComponent(g);
	}

	public char getLetra() {
		return letra;
	}

	public void setLetra(char letra) {
		this.letra = letra;
	}
}

:smiley: Bom dia a todos…

Agradeço a atenção de todos, consegui resolver o problema seguindo as orientações do usuário “gqferreira”, muito obrigado.
Como se trata de um exercício acadêmico, estou postando em anexo o código completo, para servir de base para estudos.

Abraços…