[Resolvido]Bug com JInternalFrame

Olá galera!
Bem eu estou trabalhando em um projeto no qual tenho uma tela de Login,nela o botão Logar chama a tela principal e fecha a tela de login,no JFprincipal tenho um JDesktopPane onde chamo minhas JInternalFrame e tenho tambem um botão Logoff que fecha a tela principal e chama a tela de login,o problema esta quando eu executo a ação do botão Logoff com um JInternalFrame aberto,o botão responsável por chamar o JInternalFrame que estava aberto para de chamar após o logoff e a janela não é mais mostrada até que feche o sistema completamente e o abra de novo!

Ação do botão Logar do JFlogin

JFprincipal = new tela.JFprincipal();
JFprincipal.setVisible(true);
dispose();

Ação do botão Logoff do JFprincipal

JFlogin = new tela.JFlogin();
JFlogin.setVisible(true);
dispose();

Então qual é o problema que esta acontecendo com a minha JInternalFrame?O que estou fazendo de errado?valeu…

Você tem que adicionar o JInternalFrame a um JDesktopPane. E depois adicionar o JDesktopPane ao JFrame.
Entendeu?

Codifica assim:

    public Class MenuPrincipal extends JFrame{
        private JDesktopPane pane = null;
        public MenuPrincipal(){}

        private void carregarForm(JInternalFrame frame){
               pane = new JDesktopPane();
               pane.add(frame);
               pane.setVisible(true);
               pane.setSize(500, 600);
               add(pane);
        }

      //evento do click do botão

      JInternalFrame formFuncionario = new JInternalFrame();
      carregarForm(formFuncionario);
    }

entendeu?

Bom, espero ter ajudado de alguma forma.

Olá marcoslogan!
Obrigado pela atenção,eu estou conseguindo chamar as JInternalFrame no meu JDesktopPane normalmente,o problema esta quando eu fecho o JFrame principal com o dispose(); com um JInternalFrame aberto,depois do Logoff o botão não consegue abrir aquele JInternalFrame que estava aberto…

Devido o bug permanecer até o sistema ser fechado completamente,acho que seja algo relacionado com a memória … Espero a ajuda da galera ai valeu! :smiley:

Pq você não encerra de vez a aplicação?

Fiz um teste rápido aqui e funcionou normal, acho que você ta errando em alguma coisa, se quiser deixar um exemplo simplificado do que você fez para mim executar aqui procuro onde está esse erro.

Como voce fecha o internalframe ? se nao fecha, na acao de logoff pode implementar a acao de fecha-lo, ja que fez logoff, nao precisa ficar aberto certo ?

hide()

marcoslogan eu tenho que ter uma forma de alternar entre usuário (Administrador,funcionário) rapidamente,sem ser obrigado a fechar e abrir novamente o sistema,é um sistema para venda de celulares,por isso a ideia de uma ação de logoff.

rof20004 eu não tenho nenhum método que verifique todas JInternalFrame abertas e feche antes,apenas estou executando um dispose(); no JFrame principal e chamando a tela de Login.Você tem alguma ideia de como eu poderia fazer essa verificação?

Ivan Alves eu estou fazendo assim:

Eu tenho um pacote funcao,nele tenho uma Classe com o nome Abre,com os métodos para abrir todas as minhas JInternalFrames.

A classe Abre de forma reduzida:

package funcao;

public class Abre {
    private static javax.swing.JInternalFrame JIfuncionario;

public static void funcionario()
    {
        if(JIfuncionario == null || JIfuncionario.isVisible() == false)
        {
            JIfuncionario = new tela.JIfuncionario();//tela é o nome do pacote das janelas
            tela.JFprincipal.jdarea.add(JIfuncionario);//jdarea é o meu JDesktopPane
            JIfuncionario.setVisible(true);
            
        }
        else
        {
            JIfuncionario.toFront();// traz a janela funcionario para frente
        }
    }

No JFprincipal eu tenho os JButton para fazer a ação de abrir as JInternalFrame,no caso:

private void btfuncionarioActionPerformed(java.awt.event.ActionEvent evt) {                                              
        funcao.Abre.funcionario();
    }

O evento do botão Logoff:

private void btlogoffActionPerformed(java.awt.event.ActionEvent evt) {                                         
        JFlogin = new tela.JFlogin();
        JFlogin.setVisible(true);
        dispose();
}

O evento do botão Logar:

private void btlogarActionPerformed(java.awt.event.ActionEvent evt) {                                        
        JFprincipal = new tela.JFprincipal();
        JFprincipal.setVisible(true);
        dispose();
}

Ao fazer o logoff com alguma JInternalFrame aberta,o evento do botão responsável por ela não consegue mais abrir até a aplicação ser finalizada completamente.Não sei se estou conseguindo explicar,mas qualquer coisa é só perguntar… Obrigado pela atenção!

Bom dia José Douglas.

Bem, eu tenho casos parecidos com o seu. No meu caso, tanto para a tela de logoff qto para outras funcionalidades do sistema (que utilizam JInternalFrame) que não podem ser concorrentes, a melhor ação que achei (tanto do ponto de vista prático, qto de geração de erros, qdo de interface) foi bloquear os botões de acesso.

Assim, toda vez que uma tela específica (como o citado) é aberta, eu faço um setEnable(false) nos botões específicos (como o citado).
Provavelmente não é a melhor prática, mas em algumas app desktops que conheço de outros fabricantes, vi que alguns limitam estas funcionalidades desta forma. Então, apenas repliquei.

Comigo está dando certo, a qtde de erros e reclamações minimizou drasticamente.

Abcs

Uma coisa você sempre cria o objeto para a tela de login quando passa da tela de login para a tela principal?

Ou você guarda o objeto gerado pela primeira chamada e assim que fazer logoff não chama ele novamente?

Outra coisa quando seu método funcionario possui um erro veja abaixo a forma certa

[code]public static void funcionario()
{
if(JIfuncionario == null)
{
JIfuncionario = new tela.JIfuncionario();//tela é o nome do pacote das janelas
tela.JFprincipal.jdarea.add(JIfuncionario);//jdarea é o meu JDesktopPane

    }
    if(JIfuncionario.isVisible() == false)  
    {
        JIfuncionario.setVisible(true);
    }
    JIfuncionario.toFront();// traz a janela funcionario para frente  
}[/code]

ou assim:

[code]public static void funcionario()
{
if(JIfuncionario == null)
{
JIfuncionario = new tela.JIfuncionario();//tela é o nome do pacote das janelas
tela.JFprincipal.jdarea.add(JIfuncionario);//jdarea é o meu JDesktopPane

    }
    JIfuncionario.setVisible(false);
    JIfuncionario.setVisible(true);
    try {//caso ele esteja minimizado então maximize-o
        JIfuncionario.setIcon(false);
    } catch (PropertyVetoException ex) {}
    
}[/code]

Tenta ai, flw!

Olá berg.pb!
Eu também pensei em fazer isso e seria uma boa solução,mas a ideia é que fosse possivel minimizar uma janela e abrir outra,para fazer uma consulta de um produto por exemplo,e não ser obrigado a terminar aquela operação para poder começar outra…

Ivan Alves

Eu não sei se consegui entender a sua pergunta,mas na tela de Login eu estou instanciando o objeto tela principal:

private javax.swing.JFrame JFprincipal;

E no evento do btlogar.

JFprincipal = new tela.JFprincipal();

E na tela principal eu estou instanciando o objeto login:

 private javax.swing.JFrame JFlogin;

E no evento do btlogoff.

JFlogin = new tela.JFlogin();

Eu testei aqui as duas versões dos seus métodos funcionario e não funcionou,com eles o evento do botão só funciona uma vez e depois não consegue mais abrir,a janela abre e eu fecho (sem fazer o logoff) e tento abrir novamente mas a janela não abre…

Opa.
Bem como eu disse, telas que nao sao concorrentes nos dados ou que poem em risco a app podem ser aberta.
DO MEU PONTO DE VISTA, para a tela de login (troca de user), o fechamento das outras telas abertas deve ser obrigatorio, uma vez que usuarios podem ter privilegios diferentes.

Por isso que faco esse disable no botao de login.

Mas cada caso eh uma cabeca!! :slight_smile:

Abc

Também tem uma propriedade no seu JInternalFrame que deve ficar assim:

.
.
.
if(JIfuncionario == null)    
        {    
            JIfuncionario = new tela.JIfuncionario();//tela é o nome do pacote das janelas
            JIfuncionario.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE); //coloque a depois que criar a sua instancia
.
.
.

se ela estiver assim ela só funcionará uma vez:

JIfuncionario.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE); //modo incorreto

Outra dica não nomeie as variáveis com letras maiúsculas veja um tutorial de boas práticas aqui
http://www.jardelmorais.com/java/dicas/nomenclaturas-java/

Se não funcionar você terá que passar o seu projeto com essa parte funcionando para a gente testar aqui, flw!

Ivan Alves

Alterei o defaultCloseOperation para HIDE_ON_CLOSE e seu método funcionou apenas no fato de conseguir “abrir” mais do que uma vez,porém a questão do logoff ainda permanece o bug.Mas até onde eu sei o HIDE_ON_CLOSE apenas invoca o método setVisible(false); e seu método funcionario o torna visível novamente,então qualquer alteração na janela(movimentar,inserir dados nos campos…) permanece ao chamar o método de abrir a janela,e não é criada outra janela pois apenas esta invisível!

Vou criar um outro projeto simplificado com base nesse e postar aqui! Flw!

Esta ai o projeto exemplo para a verificação do bug!Obrigado pela atenção! flw!

[quote]
Eu também pensei em fazer isso e seria uma boa solução,mas a ideia é que fosse possivel minimizar uma janela e abrir outra,para fazer uma consulta de um produto por exemplo,e não ser obrigado a terminar aquela operação para poder começar outra… [/quote]

Acho que seria bem melhor se voce fizesse isso em Abas, ao inves de ficar minimizando e/ou restaurando janelas.

O erro principal além daquele citados está na sua lógica quando você cria a classe Abre e atribui os objetos da JInternalFrame como estatico. Na primeira vez vai executar já que ele adiciona o seu JInternalFrame no seu objeto recem criado da classe principal, depois de fechado você recria um novo objeto pra classe principal, porém seu JInternalFrame ja havia sido adicionado no antigo objeto da sua classe principal(Que não está visivel), estão quando você abre ele executa a linha:

Nada aparecerá já que a instância da sua classe principal que ele foi adicionado não está visível. Segue abaixo o projeto com algumas alterações e seguindo boas práticas de programação(principalmente em nomes de variáveis)

Obs.: Evite colocar o caminho completo para sua classe quando não é necessário. Exemplo:

tente importar seu pacote e apenas usar o nome da sua classe em seguida seu método. Exemplo:

Tente ler esse tutorial também.

Segue projeto corrigido:

José, a solução é simples. Experimente apenas mudar na classe Abre o método de acesso de uma janela por exemplo (JIfuncionario - cadastro de funcionário) para public, só para testar, assim:

Salva, e volta lá para seu JFprincipal no evento do btlogoff (btlogoffActionPerformed()). Agora acrescenta abaixo do dispose() assim:

Testa abrindo a tela de funcionário, logoff, e abre a mesma em outra conta.
Simples, funciona e pronto!

Agora pra eu dormir mais feliz ainda, faz um método ai igual eu fiz aqui oh e nem precisa mudar os privates para public, la na classe Abre:

public static void fechatudo() { JIfuncionario=null; JIlogradouro=null; JIcons_funcionario=null; JIcliente=null; JIcons_cliente=null; JIaparelho=null; JIcons_aparelho=null; JIvenda=null; JIcons_venda=null; JIrelatorio=null; }

Ai aonde você colocou no evento do botão o método logoff que testou aquela linha, tira ela e só chama o método na classe, assim:

private void btlogoffActionPerformed(java.awt.event.ActionEvent evt) { JFlogin = new tela.JFlogin(); JFlogin.setVisible(true); dispose(); Abre.fechatudo(); }

Pronto! Agora vou descansar. Bons estudos!

Obrigado a todos pela ajuda!
Atribuindo null resolveu o problema,então eu adicionei o método na classe para atribuir a todas JInternalFrame!Valeu! :smiley: