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.
ja me falaram de usar singleton, porem eu nao faço ideia…
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 já 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 já foi instanciado o metodo getInstance vai retorna a instancia já 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
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.
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.
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.
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++.
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?