Não deixar abrir Form JFRAME mais de uma vez [não resolvido]

12 respostas
MrDataFlex

Galera… tenho aqui um programa que estou desenvolvendo, porém achei um bug…
cada vez que é chamado um form JFRAME pelo menu, ele cria uma nova instancia… porém, eu não quero que o mesmo formulário se repita caso ele ja esteja aberto…

eu tentei assim:

private Form f = null;

no método que chama:

if (f == null) { f = mew Form(); f.setVisible(true); }

porém, se eu fexo o form… F não vira null mais. :frowning:

ja me falaram de usar singleton, porem eu nao faço ideia…

alguem teria uma dica?

12 Respostas

herbertpimentel

Para resolver esse problema vc deve mesmo usar o padrao singleton. ele é um padrao bem simples, consistem em criar uma variavel static e ocultar o construtor da classe fazendo com que toda as vezes que vc desejar um instancia da classe utilize um metodo public static para obete-la esse metodo é comunmente chamdo de getInstance() vc provavelmente já usou uma classe da API java que usa singleton:

veja como ficaria a classe SingletonClass só pode ser instancia uma unica vez assim como vc desejä:

public class SingletonClass

{

//variavel que guardará a instancia a ser retornada qunado  existir uma

private static SingletonClass instance = null;

//define o construtor como private assim não seá possivel instanciar a classe externamente
private SingletonClass() { }

//método que pode ser utilizado para “instanciar” a classe

public static SingletonClass getInstance()

{

if (instance == null)

instance = new SingletonClass();
return instance;

}
}

class SingletonTest
{

public static void main(String args[])
  {
        //nesse momento ele instancia uma nova classe
        SingletonClass single = SingletonClass.getInstance();

       //como  foi instanciado o metodo getInstance vai retorna a instancia  armazenada no variavel static
       SingletonClass single2 = SingletonClass.getInstance();

}

toda a logica do padrao singleton esta na verdade na variavel static intance e no metodo static getInstance() note que ele é quem diz se deve ser criada uma nova instancia ou será sempre retornada a instancia já existente armazenada na variavel :slight_smile:

espero ter ajudado…

MrDataFlex

Olá amigo,
primeiramente muito obrigado pela resposta…

Deu um probleminha, que eu ja tinha com o outro modo que fazia:

Na primeira chamada, ele abre ok, e não deixa abrir outros, PORÉM quando eu fecho a tela e tento abrir de novo, nada acontece.

Alguma dica pessoal :?:

Obrigadão irmãos!!! :thumbup:

MrDataFlex

ngm nunca fez isso pessoal? :S

ViniGodoy

Você não precisa usar o Singleton, necessariamente.

Se você não quer criar mais instâncias e seu form estava sendo chamado através de apenas uma tela, bastaria fazer o que você já estava fazendo, mas colocando o setVisible para fora do if:

public void abreForm() { if (f == null) { f = mew Form(); } f.setVisible(true); }

Como f não fica null novamente (coisa que você já constatou), ele não será recriado.

MrDataFlex

isso não deixara o programa lento uma vez que se eu abrir N form’S e todos vão ficando na memória?

ViniGodoy

O ambiente onde está rodando é muito restrito em memória? Haverá num dado momento de tempo, muitos frames abertos? Os frames possuem muita informação interna?

Normalmente, isso não constitui um problema. Em alguns casos pode ser necessário “esvaziar” algumas estruturas internas do frame ao fecha-lo (como JTables).

Outra alternativa seria adicionar um WindowListener a janela anterior e, sempre que seu frame for fechado, definir a variável f para null.

Quanto a velocidade. Geralmente é mais rápido não recriar o frame toda vez. Se ele já está na memória, a aplicação rapidamente pode torna-lo visível. É o velho trade off de memória vs processamento.

Tudo vai depender do ambiente em que você estiver rodando sua aplicação.

herbertpimentel

para resover o problema, se vc optar por usar o padrão singleton, o que vc tem que fazer é sobrescrever o destrutor, ou o metodo close, da classe para que assim que o form for fechado setar novamente o valor null para variavel static.

então basta colocar mais esse método na sua classe SingletonClass

public void dispose()
{
    super.dispose();
    instance = null;
}

Isso resolve o problema. Desculpe não ter dado a informação correta logo de primeira. :frowning:

ViniGodoy

Herbert,

O método dispose não deve ser colocado num singleton. No java, graças ao Garbage Collector, ele pode gerar mais de uma cópia do objeto. Isso acontecerá se uma classe criar uma referência externa ao Singleton.

Para ver mais detalhes sobre esse problema, leia este artigo.

Sua dica funcionaria bem em linguagens sem garbage collector, como o C++.

Luca

Olá

MrDataFlex em 16/05/2007 às 11:31:53:

Alguma dica pessoal

MrDataFlex em 16/05/2007 às 12:29:01:

ngm nunca fez isso pessoal?

  1. Porque 2 mensagens logo em seguida?

  2. O que seria ngm?

[]s
Luca

MrDataFlex

Não entendi sua ajuda, Luca. Se está falando das regras, não vi nada de indiferente em mandar duas mensagens.

koproski

Pessoal, procurando no fórum pela solução do meu problema, encontrei este post, que pelo que vi ainda não está resolvido (Fechado), então, preciso de uma dica para o seguinte problema:

Tenho dois JFrame em minha aplicação, no JFrame1 possuo um JMenu com um JMenuItem que tem a função de abrir o JFrame2, até aí tudo bem se não fosse pelo fato de todas às vezes que eu clico no JMenuItem ele abrir vários JFrame2, segue abaixo o código que estou utilizando para abrir o JFrame2 pelo JMenuItem do JFrame1:

private void jMenuItem_AbrirJFrame2ActionPerformed(java.awt.event.ActionEvent evt) 
{
      new JFrame2().setVisible(true);
}

Como proteger de forma que o JFrame2 possa ser aberto novamente somente se estiver fechado?

Obrigado pela ajuda!
Abraço,
Rodrigo

koproski

Galera, desculpe pela pergunta tão básica, consegui encontrar a solução através de outro tópico respondido pelo ViniGodoy neste link:

fiz desta forma:
No início do código do formulário JFrame1 fiz conforme o ViniGodoy falou:

public class JFrame1 extends javax.swing.JFrame 
{
    JFrame2 Frame2=null;
.....código
}

E no evento ActionPerformed do JMenuItem coloquei o seguinte código:

if (Frame2 == null) {   
        Frame2 = new JFrame2();   
}   
Frame2.setVisible(true);

Deu certo, desculpem se a dúvida era básica para vocês, para mim não foi tanto, mas, está aí a resposta se caso outro novato precisar.

Parabéns pelo fórum, muito bom!!!
Abraço,
Rodrigo

Criado 16 de maio de 2007
Ultima resposta 3 de ago. de 2011
Respostas 12
Participantes 5