Singleton

11 respostas
Diegomoco

Sou meio que iniciante em java e to com uma dúvida.

Tenho um MainFrame que é um Singleton, e tenho dentro do MainFrame um JSplitPane. Dentro do JSplitPane tem um menu, e quando clicar num intem do menu queria que o lado direito do JSplitPane setasse outro JPanel.

Tentei mais ou menos assim:

MainFrame.getInstance().getMainSplitPane.setRigthComponent(new panel);

mas assim não deu certo, e o action listener do botão ta funcionando certinho porque testei no console.

Assim ta certo? Toda vez que eu clicar em um item do menu ele vai ter que mudar o panel, entao essa é a melhor maneira de fazer mesmo?

11 Respostas

fantomas

Inclua o código no tópio, quem sabe a galera se anima a lhe ajudar.

P.S Não se esqueça de utilizar a tag [code]

flws

Diegomoco

Não tinha colocado o código porque não tenho muito o que mostrar, mas aí vai.

O Singleton:
public static MainFrame getInstance() {
		if (_mainFrame == null) {
			_mainFrame = new MainFrame();
		}
		
		return _mainFrame;
	}
o método do JSplitPane
public JSplitPane getMainSplitPane() {
		_panelLogin = new PanelLogin();
		_mainSplitPane = new JSplitPane();
		_panelLogin.setListener(this);
		_mainSplitPane.setOpaque(true);
		_mainSplitPane.setLeftComponent(_panelLogin);
		_mainSplitPane.setRightComponent(new MainPanelImage());
		_mainSplitPane.setDividerLocation(380);
		return _mainSplitPane;
	}
O método do link que vai é para setar um jpanel do lado direito do JSplitPane quando for clicado.
link1.setText("Link 1");
		link1.setIcon(new ImageIcon("resources/icons/ambulance.png"));
		link1.setForeground(Color.BLACK);
		link1.addActionListener(new ActionListener() {
		
			@Override
			public void actionPerformed(ActionEvent e) {
				MainFrame.getInstance().getMainSplitPane.setRightComponent(new PanelPatientRegister);
			}
		});

Quando clicado ele simplismente não faz nada!

:?:

fantomas

Oi Diegomoco,

Verifiquei teu código e observei um ponto intrigante, que é o seguinte:
MainFrame.getInstance().getMainSplitPane.setRightComponent(new PanelPatientRegister);

O método getInstance() fornece um JFrame que por sua vez possui o método getMainSplitPane que fornece um JSplitPane, e ai vem a grande pergunta: VOCÊ ESTÁ ADICIONANDO ESTE PAINEL (JSplitPane) ONDE? A principio, os paineis tem que estar adicionados em algum JFrame para que possam ser visualizados.

Verifique este ponto, pode ser este o seu problema.

flws

Diegomoco

O método getInstance() fornece um JFrame que por sua vez possui o método getMainSplitPane que fornece um JSplitPane, e ai vem a grande pergunta: VOCÊ ESTÁ ADICIONANDO ESTE PAINEL (JSplitPane) ONDE? A principio, os paineis tem que estar adicionados em algum JFrame para que possam ser visualizados.

Verifique este ponto, pode ser este o seu problema.

flws

Este JSplitPane está já está adicionado no MainFrame (que é o singleton). Inclusive o lado esquerdo do Jsplitpane é onde aparece o menu com o link que eu postei aí.

ViniGodoy

Outra coisa, faltou () depois de
getMainSplitPane
e depois de:
new PanelPatientRegister

O código ficaria assim:

MainFrame.getInstance().getMainSplitPane().setRightComponent(new PanelPatientRegister());

Seu IDE não ressaltou esse erro para você?

fantomas

Humm... vamos tentar uma outra coisa então, este código abaixo é uma maneira de isolar a questão da troca de paineis no JSplitPane e verificar se vc está fazendo tudo certo NESTE PONTO.

public class FramePrincipal extends JFrame {
    private int countLeft = 1;
    private int countRight = 1;
    
    private JButton btnLeft = new JButton("Left");
    private JButton btnRight = new JButton("Right");
    
    JSplitPane _mainSplitPane = new JSplitPane();   
    
    public FramePrincipal() {
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setSize(400,400);
        super.setLocationRelativeTo(null);

        _mainSplitPane.setOpaque(true);   
        _mainSplitPane.setLeftComponent(new PainelLeft(countLeft));   
        _mainSplitPane.setResizeWeight(1);
        _mainSplitPane.setRightComponent(new PainelRight(countRight));
        _mainSplitPane.setDividerSize(4);
        _mainSplitPane.setDividerLocation(200);
        
        btnLeft.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                _mainSplitPane.setLeftComponent(new PainelLeft(++countLeft));   
            }
            
        });
        
        btnRight.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                _mainSplitPane.setRightComponent(new PainelLeft(++countRight));   
            }
            
        });

        JPanel south = new JPanel(new FlowLayout());
        south.add(btnLeft);
        south.add(btnRight);
        
        this.getContentPane().add(_mainSplitPane, BorderLayout.CENTER);
        this.getContentPane().add(south, BorderLayout.SOUTH);
        
        this.setVisible(true);
    }
    
    public static void main(String[] args) {
        FramePrincipal frame = new FramePrincipal();
    }
}
public class PainelLeft extends JPanel {
    
    public PainelLeft(int count) {
        super.add(new JLabel("E sou lado Left, objeto "+count), BorderLayout.CENTER);
    }

}
public class PainelRight extends JPanel {
    public PainelRight(int count) {
        super.add(new JLabel("E sou lado Right, objeto "+count), BorderLayout.CENTER);
    }
}

Também verifique o objeto criado pela classe PanelPatientRegister, certifique-se de que não há exceptions sendo emitidas, loops ou threads atrapalhando a formação deste objeto ou causando mal comportamento.

flws

Diegomoco

Outra coisa, faltou () depois de
getMainSplitPane
e depois de:
new PanelPatientRegister

O código ficaria assim:
view plaincopy to clipboardprint?

  1. MainFrame.getInstance().getMainSplitPane().setRightComponent(new PanelPatientRegister());

MainFrame.getInstance().getMainSplitPane().setRightComponent(new PanelPatientRegister());

Na verdade eu escrevi esse aqui agora, e essa parte do código ta certo no meu notebook que não está aqui, lá esta com os () certinho.

Diegomoco

Fantomas,
Pelo que entendi do seu código vai ter um botão e um label que vai mudando a contagem conforme você vai clicando no botão certo?, isso dos dois lados. Algo assim não é.

Mas o fazer isso eu estou até conseguindo. O Difícil ta sendo fazer isso em outra classe.

Tipo tenho um botão em um JPanel no lado esquerdo e quando clicado quero que ele altere o jpanel do lado direito do JsplitPane que se encontra em um JFrame.
O problema é que na classe eu pego o _mainSplitPane já instanciado e seto o contentPane. Agora de outra classe eu acessar o JFrame pra setar o JSplitPane que está nele é mais difícil e isso que não estou conserguindo.

Não é tirando não, mas você entendeu o que é minha dúvida? por que eu sou ruim pra explicar mesmo hehehe.

Até então obrigado.

Ha mais uma coisa, Update UI serve pra atualizar o panel de um contentPanel?

fantomas

Então...tem uma coisa no teu código de que não estou convencido de que está certo, vou tentar lhe mostrar.

public JSplitPane getMainSplitPane() {
      _panelLogin = new PanelLogin();
      _mainSplitPane = new JSplitPane();  // <---------------------------<< NOVA instancia sendo criada.
      _panelLogin.setListener(this);
      _mainSplitPane.setOpaque(true);
      _mainSplitPane.setLeftComponent(_panelLogin);
      _mainSplitPane.setRightComponent(new MainPanelImage());
      _mainSplitPane.setDividerLocation(380);
   return _mainSplitPane;
}
link1.setText("Link 1");
link1.setIcon(new ImageIcon("resources/icons/ambulance.png"));
link1.setForeground(Color.BLACK);
link1.addActionListener(new ActionListener() {
		
     @Override
      public void actionPerformed(ActionEvent e) {
	          MainFrame.getInstance().getMainSplitPane.setRightComponent(new PanelPatientRegister); // <---<< PONTO DE ATENÇÂO
      }
});

Agora vamos falar desta parte aqui MainFrame.getInstance().getMainSplitPane.setRightComponent(new PanelPatientRegister);

Vou dividir isto em passos para tentar facilitar.

1) MainFrame.getInstance() <---- Isto retorna a istancia (Singleton) do JFrame
2) getMainSplitPane() <-- Executa este método (está no objeto JFrame Singleton) que retorna MAIS UMA (a anterior vc já está vendo) instancia (NOVA) de uma JSplitPane
3) setRightComponent(new PanelPatientRegister) <--- Executa este método que está na NOVA instancia da JSplitPane, passando como parametro uma instancia da PanelPatientRegister.

O que deve estar acontecendo é que logo no inicio da execução vc executa o método getMainSplitPane() pega a instancia JSplitPane retornada e inclui no painel do JFrame (Singleton ). Depoi quando vc clica no botão o método getMainSplitPane() é acionado DE NOVO gerando MAIS UMA instancia JSplitPane que NÂO é adicionada em lugar nenhum ( veja o passo 2 ), por isso que vc não vê os componentes que estão na instancia da classe PanelPatientRegister.

Esta linha _mainSplitPane = new JSplitPane(); esta substituindo (matando) o endereço da instancia ANTERIOR quando vc clica no botão.

Tem mais outra coisa, este método getMainSplitPane() é um "getter" e como tal deveria apenas lhe devolver o objeto _mainSplitPane da seguinte forma:

public JSplitPane getMainSplitPane() {
	return _mainSplitPane;
}

o restante do código que retirei de dentro só deveria ser executado UMA UNICA VEZ.

Desculpe se viajei muito...

flws

Diegomoco

Aew Fantomas!
Deu certo! que dizer, funcionou! rsrs

Era mais ou menos o que você falou mesmo, quando eu estava chamando o método getSplitPane ele estava cirando uma nova instancia sem adicionar em lugar nenhum, ao invés de pegar o JSplitPane que já estava no singleton.

pra resolver fiz isso:

public JSplitPane getMainSplitPane() {  
          if(_mainSplitPane == null){                // <-------------------<< *                      
          _panelLogin = new PanelLogin();  
          _mainSplitPane = new JSplitPane();   
          _panelLogin.setListener(this);  
          _mainSplitPane.setOpaque(true);  
         _mainSplitPane.setLeftComponent(_panelLogin);  
          _mainSplitPane.setRightComponent(new MainPanelImage());  
          _mainSplitPane.setDividerLocation(380);  
          }
       return _mainSplitPane;  
   }

*Só cria uma nova instancia se a variavel estiver nula ou seja, teoricamente só na primeira vez que o método é chamado.

Quanto ao que você disse sobre o método get só retornar o item(no caso JSplitPane), eu uso ele sempre desse modo aí acima. Sempre verifico se ele é nulo e já seto as propriedades no get mesmo. Verifico se é nulo para não ter problema de null pointer e seto ali pra fica mais dividido o código. Acho que tem mais gente que faz assim, e pelo pouco que conheço este jeito parece legal.

No mais muito obrigado pelo empenho que resultou na solução. Agora ta tudo funcionando aqui hehehe

Valeu

fantomas

É isso ai garoto.

System.out.println(“Keep walking!”);

Criado 3 de novembro de 2008
Ultima resposta 4 de nov. de 2008
Respostas 11
Participantes 3