Multiplos JFrames

Boa tarde,

estou trabalhando com 2 JFrames que funcionam simultaneamente na minha aplicação, eis que estou tendo o seguinte problema.
Ao rodar a aplicação (tanto debugando quanto gerando um .jar) eu não sei por que ele executa 4 frames, sendo 2 copiados dos 2 existentes. 2 frames 1 e 2 frames 2. E as cópias não tem nenhum ActionListener pois quando clico em qualquer botão delas nenhuma ação é executada.

Por que está acontecendo isso e como eu faço pra rodar apenas os 2 frames que desejo?

Desculpa o double post, mas é que eu realmente não consegui descubrir a fonte do problema e preciso muito da ajuda de alguém mais experiente que soubesse o que pode ser isso.

Eu desconheço o motivo, mas meu programa esta rodando os JFrames dobrados, sempre abrem 2 iguais de cada um que existe. Aonde eu acabei mechendo que não deveria?

Desde ja, obrigado.

Só existe um único motivo para estar abrindo dobrado.
Você está mandando abrir cada frame duas vezes.

Poste seu código. Fica difícil ajudar no achismo.

PS: Já tentou rodar passo-a-passo, com um depurador?

Oi Sucrylhus,

Não sei por que esta acontencendo isso…Esse tipo de coisas “estranhas” as vezes acontece…Crie um projeto novo… :wink:

[quote=ViniGodoy]Só existe um único motivo para estar abrindo dobrado.
Você está mandando abrir cada frame duas vezes.

Poste seu código. Fica difícil ajudar no achismo.

PS: Já tentou rodar passo-a-passo, com um depurador?[/quote]

Opa desculpe…acho que postamos ao mesmo tempo… :roll:

Estou indo pro trabalho agora, de lá eu posto o código.

Que parte do código interessa pra achar isso, os forms (view) ou meu gerenciador(control)?

E eu sou meio leigo, não rodei com depurador por não saber fazer isso no java, se puder me explicar como o faço eu tento pra descobrir o erro.

Se você usa o Netbeans, é assim:
[youtube]http://www.youtube.com/watch?v=joWldbcp1So[/youtube]

Se você usa eclipse, é assim:
[youtube]http://www.youtube.com/watch?v=WeSitNPAExg[/youtube]

É interessante postar os trechos de código onde você dá setVisible(true) nos seus forms, e onde você dá new neles também.

Não esqueça de usar a tag code. Ou, se o código for muito grande, de usar a opção de attachments.

Bom, agradeço sua atenção. Então vamos la:

Não pude ver os vídeos aqui do trabalho por causa do proxy, depois dou uma olhada.

Agora vamos aos códigos. Eu não usei nenhum botão que chame o segundo form, simplesmente dei um setvisible(true) nos 2 para abrirem juntos ao rodar a aplicação.

Form1:

[code] public Frmsenha() {
super();
initialize();
}

private void initialize() {
	this.setContentPane(getJContentPane());
	this.setTitle("Senha");
	this.setBounds(new Rectangle(0, 0, 328, 258));
	this.setResizable(false);
	this.setVisible(true);
}[/code]

Form2:

[code]public Frmexibesenha() {
super();
initialize();
}

private void initialize() {
	this.setContentPane(getJContentPane());
	this.setTitle("Senha");
	this.setEnabled(true);
	this.setResizable(false);
	this.setBounds(new Rectangle(0, 0, 800, 600));
	this.setVisible(true);
}[/code]

Eu não notei nada de errado, ou nenhuma vez inicializei os forms duas vezes. Se quiser alguma outra parte do código aonde possa estar o erro é só falar.

Eu ja revirei esse código de ponta cabeça mas não consegui achar o erro. Não sei se é pq sou leigo até de mais ou se pq fiz cagada em nível avançado.

E cadê o local onde você dá new nos frames?

Uma coisa, é uma péssima prática de programação chamar o setVisible no construtor do seu JFrame.

Desculpa o código mal elaborado, estou no java a pouco tempo.

Aonde você chamaria o setvisible do frame então para ele aparecer assim que eu rode a aplicação?

Quanto ao new, é a isso que você se refere?

	public JPanel getJContentPane() {
		if (jContentPane == null) {
			lblChamar = new JLabel();
			lblChamar.setBounds(new Rectangle(12, 13, 191, 16));
			lblChamar.setForeground(Color.white);
			lblChamar.setText("Digite a senha a ser chamada:");
			jContentPane = new JPanel();
			ButtonGroup bg = new ButtonGroup();
			jContentPane.setLayout(null);
			jContentPane.setBackground(Color.black);
			jContentPane.add(getTxtSenha(), null);
			jContentPane.add(getBtChamar(), null);
			jContentPane.add(getBtSair(), null);
			jContentPane.add(lblChamar, null);
			jContentPane.add(getRdPreferencial(), null);
			jContentPane.add(getRdCnh(), null);
			jContentPane.add(getRdRg(), null);
			jContentPane.add(getRdDservicos(), null);
			jContentPane.add(getBtRepetir(), null);
			bg.add(rdPreferencial);
			bg.add(rdCnh);
			bg.add(rdDservicos);
			bg.add(rdRg);
			txtSenha.setDocument(new FixedLengthDocument(3));
			rdDservicos.setSelected(true);

		}
		return jContentPane;
	}

Se não for isso, o que é? Desculpe se estou complicando de mais a sua ajuda com tanta pergunta hehe.

@Edit:

A partir do que você me falou sobre o setvisible no construtor do JFrame eu estava tentando aplicar de outro modo com o frame iria aparecer.

Tentei colocar o seguinte código na minha classe Principal.

public static void main(String[] args) { Frmsenha form = new Frmsenha(); Frmexibesenha form1 = new Frmexibesenha(); form.show(true); form.setAlwaysOnTop(true); form1.show(); new GerenciadorSenha(); }

Com esse código acontece tudo certo, abrem somente 2 frames (1 de cada) e não são dobrados, porém parece que minha classe GerenciadorSenha não é aplicada a ambos os JFrames pois todos meus botões perdem as ações.

@Edit²

Creio que descobri como fixar o problema. Joguei o .show no construtor do meu gerenciador, segue o código:

[code]package Control;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import Model.Senha;
import View.Frmexibesenha;
import View.Frmsenha;

public class GerenciadorSenha implements ActionListener {
//objeto clip
private AudioClip clip;
//objetos forms
public Frmsenha form;
public Frmexibesenha form1;
//objeto da classe de modelagem
Senha c = new Senha();

//construtor
public GerenciadorSenha(){
	form = new Frmsenha();
	form1 = new Frmexibesenha();
	form.configurarOuvinte(this);
	form.setAlwaysOnTop(true);
	form.show(true);
	form.setAlwaysOnTop(true);
	form1.show();

}

[/code]

É assim mesmo que você me aconselha fazer?

Se ainda sim não for ai que você chama os frames, aonde é então?

Então. Veja seu código. Você cria e exibe no main os JFrames.
Em seguida, você chama o GerenciadorSenha, que cria e exibe os frames novamente em seu construtor.

Como você está criando exibindo cada um duas vezes, são duas janelas exibidas.

Do jeito que está, basta mudar seu main para:

public static void main(String[] args) {
   new GerenciadorSenha();
}

Ou, ainda melhor:

public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { new GerenciadorSenha(); } }); }

Quanto ao setVisible. O ideal é deixar ele fora do construtor. Aí, quem der o “new” é quem chama o método.

Outra coisa. Conforme a documentação do Javadoc explica, o método show é deprecated. Use o setVisible no lugar, sempre.

É, eu mudei aqui pro setvisible por causa desse deprecated. Muitíssimo obrigado pela ajuda, agora se não for abusar muito da boa vontade, você pode me explicar esse código que você disse que ficaria melhor? Qual diferença de usar ele ou não usar?

public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { new GerenciadorSenha(); } }); }

O Swing tem uma Thread própria, e ações sobre seus componentes devem ser feitas nessa thread.

Entretanto, o main roda numa thread separada, chamada, a thread principal.

O código que postei no início faz com que o main empilhe um pedido para a Thread do Swing. Isso quem faz é o método EventQueue.invokeLater.
O Swing então desempilha um evento dessa fila (no caso, o pedido para criar um GerenciadorSenha) e o executa.

Assim você garante que suas janelas são criadas na Thread do Swing, e não na main.

Entendi então o por que desse EventQueue.invokeLater.

Muito obrigado pela sua ajuda.

ViniGodoy
isso eu costumo fazer tambem, sempre coloco o setVisible na chamada new e nao no construtor do objeto

Agora sobre isso ser uma boa prática ou não, to na dúvida rsrs

O maquiavélico NetBeans(pelo menos o q estou usando 7.2.1)
Ele sempre cria o setVisible no main do objeto forçando o desenvolvedor a tirar o setVisible do main ou entao na chamada apenas da o new sem o setVisible

Então como vc é mais experiente que eu em java me orienta ai

como devo fazer

Sempre chamar o setVisible na chamada do objeto, tipo: new MeuFrame().setVisible(true);

ou entao

deixar o setVisible(true); no main do objeto e na chamada apenas da o new MeuFrame

O dilema viu :frowning:

O main que o netbeans cria é só uma forma conveniente de você abrir diretamente aquela janela. Normalmente, os forms não terão um main, só o primeiro form da aplicação terá.

No fundo, tanto faz. O importante é o setVisible não estar no construtor do objeto. O construtor é um ponto onde o objeto ainda não está pronto, e constitui uma má prática de programação deixar o setVisible lá (uma vez que você está mostrando algo que nem sequer está pronto ainda).