JTextArea recebe o append mas não exibe o texto adicionado

Olá pessoal.

Cá estou eu, com o trabalho final de POO2 da faculdade, precisando de ajuda.

Abaixo a tela principal. Inclui uma nova ação normalmente.:

A aba novidades tem um JTextArea, onde a cada inclusão, exclusão ou alteração, dou um append com a informação sobre a operação realizada. Porém ao clicar na aba para ler as novidades, parece que o append não funcionou:

Mas se após o append, eu exibir uma mensagem com todo o conteúdo do JTextArea, está tudo lá. Vejam a imagem abaixo, após incluir duas ações no sistema:

Alguém sabe porque isso acontece?

Tenho um JPanel, com um JScrollPane e dentro deste o JTextArea. Já tentei dar repaint() nos três componentes, sem êxito.

Segue o código da aba Novidades:

[code]public class Novidades extends JPanel implements Observer {
private Acao acao;
private JTextArea areaTexto;
private JScrollPane scrollPane;

public Novidades() {
	setLayout(new BorderLayout(0, 0));
	areaTexto = new JTextArea();
	areaTexto.setEditable(false);
	scrollPane = new JScrollPane(areaTexto);
	add(scrollPane);
	areaTexto.append(".::NOVIDADES NA BOLSA DE VALORES::.\n\n\n");
}

@Override
public void update(DadosAcoes o) {
	this.acao = o.getAcao();
	if (o.isEhNova()) {
		this.informaNova();
	} else  {
		if (o.isEhExclusao()) {
			this.informaExclusao();
		} else {
			this.informaAlteracao();
		}
	}
}

private void informaNova() {
	areaTexto.append("- Ação "+acao.getCodigo()+" negociada por "+acao.getDescricao()+" por R$ "+acao.getValor()+".\n\n");
	JOptionPane.showMessageDialog(null, areaTexto.getText());
	
}[/code]

Ajuudem! :frowning:

Não sei se entendi direito. Você quer exibir apenas a última mensagem inserida?

Está aparecendo todas as mensagens, por que vc está exibindo todo conteúdo do seu TextArea.
Pra exibir somente a última, teria que fazer algo assim:

[code]
private void informaNova() {
String ultimaNovidade = “- Ação “+acao.getCodigo()+” negociada por “+acao.getDescricao()+” por R$ “+acao.getValor()+”.\n\n”;
areaTexto.append(ultimaNovidade);
JOptionPane.showMessageDialog(null, ultimaNovidade);

}  [/code]

[quote=igor_ks]Não sei se entendi direito. Você quer exibir apenas a última mensagem inserida?

Está aparecendo todas as mensagens, por que vc está exibindo todo conteúdo do seu TextArea.
Pra exibir somente a última, teria que fazer algo assim:

[code]
private void informaNova() {
String ultimaNovidade = “- Ação “+acao.getCodigo()+” negociada por “+acao.getDescricao()+” por R$ “+acao.getValor()+”.\n\n”;
areaTexto.append(ultimaNovidade);
JOptionPane.showMessageDialog(null, ultimaNovidade);

}  [/code][/quote]

Eu preciso exibir tudo.

Ao instanciar o JTextArea, eu faço o append do título.

Durante a execução do programa, conforme operações ocorrem, é preciso reportá-las nessa área de texto. Tudo o que acontece durante a execução do programa deve ser reportado ali, serve como um “journal” das operações efetuadas. E por isso mesmo que coloquei essa área de texto com scroll, pra justamente quando encher continuar escrevendo e habilitar o scroll.

Só que todo append que eu faço nesse textArea simplesmente não é exibido no componente. Mas se eu pegar todo o conteúdo já escrito nesse textArea e mandar exibir numa JOptionPane por exemplo, está tudo lá.

O problema não está em inserir as informações, está na exibição mesmo. O componente está recebendo e armazenando as informações corretamente, porém não as exibe.

Coloca um breakpoint no seu construtor e veja se não está sendo chamado duas vezes.

Olá Vini!

Creio que não seja isso, pois se na linha abaixo da qual eu fizer o append, criar um JOptionPane pra exibir o getText() desta JTextArea, todo o conteúdo é exibido. Mas na bendita área de texto ele não aparece.

Outro fato importante é que implementei o padrão de projeto Observer, e este TextArea está numa classe Observadora. Eu instancio todos os Observadores no início da aplicação e registro-os no Subject. É um dos primeiros passos na inicialização do programa. Portanto já descartei essa possibilidade de o construtor estar sendo chamado mais vezes, pois só é possível atualizar o objeto Observer a partir de um notifyObservers() vindo do Subject, e como este objeto tem uma lista dos seus observadores, e em nenhum momento tal lista é alterada, já me certifiquei que não existe mais de uma instância desta classe Novidades rodando no meu sistema.

Enfim, já entreguei este trabalho e expliquei a situação para o professor. No fim das contas o objetivo não era avaliar interface gráfica, mas sim conceitos de POO e Design Patterns(que funcionou!).

Mas eu fiquei boladão que essa porcaria não funcionou! Odeio trabalhar com Swing! :stuck_out_tongue:

Deveria funcionar. Mas faça o que eu falei. O que as vezes acontece é ter duas instâncias, uma delas criada por acidente. Uma que está na tela, e outra que vc está atualizando.

Estou com o mesmo problema. Como você conseguiu resolver?

Não consegui resolver não cara.

No fim das contas eu fiz exibir o conteúdo do TextArea em um JOptionPane mesmo e expliquei a situação para o meu professor. Nem ele conseguiu encontrar o problema. :frowning:

Cara, eu consegui resolver colocando pra mostrar dentro de uma Thread. Pode fazer o teste que vai funcionar. Eu tava notando que ele só não escreve no Jtext quando entra em algum loop. Eu fiz disparar uma Thread e resolveu o problema, mostrava certinho dentro. Faz um teste e diga se deu certo.

Eu sei que você já entregou o seu trabalho para o professor, mas aqui neste link está a resposta para seu problema:
http://pt.stackoverflow.com/questions/25169/jtextarea-recebe-o-append-mas-n%C3%A3o-exibe-o-texto/25267#25267

[quote=bomba544]Eu sei que você já entregou o seu trabalho para o professor, mas aqui neste link está a resposta para seu problema:
http://pt.stackoverflow.com/questions/25169/jtextarea-recebe-o-append-mas-n%C3%A3o-exibe-o-texto/25267#25267[/quote]

Interessante isto.

Não consegui ler tudo, li meio por cima aqui, mas vou guardar o link pra ler com mais atenção qualquer dia desses.

Eu não sabia da existência deste SwingUtilities. :slight_smile:

Quem disparava mensagens para o observer não era uma thread separada? Eu sempre parti do pressuposto que fosse.

O método append, do contrário do contrário do setText (que o StackOverflow fala) é um dos poucos que são thread-safe.

Desculpa Vini, não sabíamos o que realmente era o problema. Eu não sabia que o frame só atualizava depois que saisse dela .-.

Saisse da Event Dispatcher Thread…

Estava falando ali da arquitetura do Ruttman. No seu código eu não saberia dizer. É que no código dele o código que chamada o JTextArea implementa observer, então, parti do pressuposto (talvez errado de minha parte) que esse observer era alimentado por outra thread.

Eu tava pensando aqui…
Então o método repaint() só vai funcionar dentro Thread Separada?

[quote=bomba544]Eu tava pensando aqui…
Então o método repaint() só vai funcionar dentro Thread Separada?[/quote]

A thread do Swing funciona assim:

while (true) { while (temMensagensNaFila()) { processaAProximaMensagem(); } if (houvePedidoDeRepaint) { repintaTela(); } yield(); }

O comando EventQueue.invokeLater coloca uma mensagem na fila do Swing.
O comando repaint, coloca outra mensagem, solicitando a repintura.

Um evento, também ocorre como resposta a uma mensagem da fila do Swing, portanto, é uma das atividades do método “processaMensagensDaFila()”. Por isso, ele trava a repintura, impedindo a tela de se redesenhar.

Isso responde a sua pergunta? Se você der um repaint num método evento de botão, só estará colocando uma mensagem a mais na fila, que não será processada até que esse evento termine e o Swing um dia chegue no pedido de repintura.

Respondida sim. Muito obrigado, de verdade.