Problema com foco inicial em JTextField ao trocar painel

1 resposta
daniel.lopes

Galera, fiz uma aplicaçãozinha simples para postar aqui. Tenho uma classe MyJFrame que é a mãe para o frame da aplicação. Tenho outra classe MyJPanel que é a mãe para todos os paineis da aplicações. Minha tela inicial instancia essa MyJFrame e depois instancia um Painel que é filha dessa MyJPane.Esse painel é adicionado ao frame principal. Pelo botão do painel troca-se os paineis do framel. Esse primeiro painel aberto recebe o foco no JTextField sem problemas, é só rodar o programa, a tela é carregada e sair digitando. Porém, ao clicar no botão para chamar o outro painel com seus devidos JTextFields, não consigo mais colocar o foco inicial neles, e nem voltando para a tela inicial. O que estou esquecendo??? segue o código:

Aplicação Controle

import javax.swing.JPanel;

public class CallFocusedTextFieldController{
	
	FramePrincipal frame;
	Focus01 focus01;
	Focus02 focus02;
	JPanel container;
	
	public void inicializa(){
		
		frame = new FramePrincipal("teste");
		//painel geral do frame
		container = new JPanel();
		
		//instanciando as classes e repassando o controller
		focus01 = new Focus01(this);
		focus02 = new Focus02(this);
		
		//inicializando a primeira tela
		focus01.inicializa();
		container.add(focus01);
		
		frame.getContentPane().add(container);
		frame.setVisible(true);
		frame.setLocationRelativeTo(null);  
	}
	
	public void evento(String evento){
		
		if (evento.equals("Chama Painel 02")){
			System.out.println("Chegou no controller");
			
			container.removeAll();
			focus02.inicializa();
			container.add(focus02);
			frame.getContentPane().add(container);
			frame.setVisible(true);

		} else if (evento.equals("Chama Painel 01")){
			System.out.println("Chegou no controller");
			container.removeAll();
			focus01.inicializa();
			container.add(focus01);
			frame.getContentPane().add(container);
			//frame.setVisible(true);
			
		} else {
			System.out.println("ERRO");
		}
	}
	
	public static void main (String[] args){
		CallFocusedTextFieldController main = new CallFocusedTextFieldController();
		main.inicializa();
	}
}

Meu Frame personalizado

import javax.swing.JFrame;

public class FramePrincipal extends JFrame{
	
	public FramePrincipal(String titulo){
		super(titulo);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(600,600);
	}
}

Meu Painel personalizado

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

public abstract class PanelMaster extends JPanel {
	
	/** Variável para utilização da aplicação de controle */
	AppController controller;
	
	/** 
	 * Contrutor da classe deve receber saber qual seu controller.
	 * Todos os painéis serão obrigados a utilizar Border Layout.
	 */
	public PanelMaster (AppController controller){
		super(new BorderLayout());
		
		this.controller = controller;
		
		setBackground(Color.RED);
		setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
	}
}

O painel principal

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Focus01 extends JPanel implements ActionListener{
	
	CallFocusedTextFieldController controller;
	JTextField tf1, tf2;
	
	public Focus01(CallFocusedTextFieldController controller){
		this.controller = controller;
	}
        
	public void inicializa(){

		setBackground(Color.RED);
		setSize(450,500);
		
		JPanel pnl= new JPanel(new GridLayout(10,10,10,10));
		pnl.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 10));
    	pnl.setPreferredSize(new Dimension(400, 400));
    	pnl.setBackground(Color.YELLOW);
    	    	
    	tf1= new JTextField(15);
    	
    	tf2 = new JTextField(15);
    	
		JButton btn = new JButton("Chama Painel 02");
		btn.addActionListener(this);
    	
    	pnl.add(tf1);
    	pnl.add(tf2);
    	pnl.add(btn);
    	
    	add(pnl);
    	tf1.requestFocus(true);
	}

	public void actionPerformed(ActionEvent e) {
		removeAll();
		System.out.println(e.getActionCommand());
		controller.evento(e.getActionCommand());
	}
}

O Painel segundario

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Focus02 extends JPanel implements ActionListener{
    
	CallFocusedTextFieldController controller;
	JTextField tf1, tf2;
	
	public Focus02(CallFocusedTextFieldController controller){
		this.controller = controller;
	}
    
	public void inicializa(){

		setBackground(Color.GREEN);
		setSize(450,500);
		
		JPanel pnl= new JPanel(new GridLayout(10,10,10,10));
		pnl.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 10));
    	pnl.setPreferredSize(new Dimension(400, 400));
    	pnl.setBackground(Color.GRAY);
    	
    	tf1= new JTextField(15);
    	
    	tf2 = new JTextField(15);
    	
		JButton btn = new JButton("Chama Painel 01");
		btn.addActionListener(this);

		pnl.add(tf1);
    	pnl.add(tf2);
    	pnl.add(btn);
    	
    	add(pnl);
    	tf1.setVisible(true);
    	tf1.requestFocus(true);
	}

	public void actionPerformed(ActionEvent e) {
		removeAll();
		System.out.println(e.getActionCommand());
		controller.evento(e.getActionCommand());

	}
}

1 Resposta

daniel.lopes

O foco do textfield do primeiro painel ao rodar a aplicação é setado sem problemas, porém, ao clicar no botão, o foco do textfield do próximo painel não é setado nem a pau. Quando volto ao primeiro painel utilizando o botão, já era o foco no textfield. Reparei que o foco só aparece nesses textfields após minimizar e restaurar a janela da aplicação.

Utilizei uma solução aqui do forum que foi utilizar essa saída:

SwingUtilities.invokeLater(new Runnable() {  
    	    public void run() {  
    	        tf1.requestFocus();  
    	    }  
    	});

Ah sim, foi implementada nos paineis, logo após a instancia do textfield.

A aplicação e os focos funcionaram corretamente, mas não estou convencido e nem esclarecido com o porquê desse tipo de problema, e porque nem o grabFocus, nem o requestFocus e nem o setFocusable SÓ funcionam ao minimizar e restaurar a janela, porém com essa solução acima não tem esse problema…

Algum companheiro que seja capaz de explicar o que acontece a esse pobre, iniciante e inexperiente programador???

Grande abraço a todos. Aguardo retorno!!!

Criado 26 de janeiro de 2008
Ultima resposta 26 de jan. de 2008
Respostas 1
Participantes 1