Duvida sobre a JList [RESOLVIDO]

ola.

estou tendo uma dificuldade aqui que a seguinte…

        jScrollPane1 = new JScrollPane();
        jList1 = new JList();
        
        jList1.setFocusable(false); // <---
        
        jList1.setSelectedIndex(0);
        jList1.setFocusCycleRoot(true);
        jList1.setModel(new AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5",
            "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12", "Item 13", "Item 14", "Item 15" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane1.setViewportView(jList1);

        getContentPane().add(jScrollPane1, BorderLayout.SOUTH);

o meu sistema nao utiliza mouse so teclado e as teclas sao predefinidas… quando eu adiciono o JList na minha tela ele ganha o focu de tudo e os eventos do teclados para de responder… se eu utilizo o setFocusable(false) o sistema roda belezinha porem o meu problema e o seguinte… eu queria utilizar duas teclas para mover entre os itens… tipo Q = sobe, W = desse… eu setei pra que ele ele marcasse os itens pelo jList1.setSelectedIndex(i); isso tmb funciona mais a barra de rolagem nao vai junto tipo se tiver espaço para mostra apenas 5 e tiver 10 itens vc consegue mover entre ele mais vc sempre vai ficar vendo os 5 pq a barra de rolagem nao acompanha os itens… eu queria saber se tem algum tipo de setFocus… ou next()… alguma coisa do tipo pra mover a barra de rolagem junto e sempre mnostrar o item selecionado.

http://www.guj.com.br/posts/list/92862.java#497384

[code]
package guj;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.KeyEvent;

import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;

public class ExemploJList extends JFrame {

private static final long serialVersionUID = 1L;

public static void main(String[] args) {
	// TODO Auto-generated method stub
	SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			ExemploJList thisClass = new ExemploJList();
			thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			thisClass.setVisible(true);
		}
	});
}

private JButton btnOK = null;
private JPanel jContentPane = null;
private DefaultListModel listModel;
private JList lstList = null;

private JPanel pnlBotoes = null;

private JScrollPane scpList = null;

public ExemploJList() {
	super();
	initialize();
}

private JButton getBtnOK() {
	if (btnOK == null) {
		btnOK = new JButton();
		btnOK.setText("OK");
	}
	return btnOK;
}

private JPanel getJContentPane() {
	if (jContentPane == null) {
		jContentPane = new JPanel();
		jContentPane.setLayout(new BorderLayout());
		jContentPane.add(getScpList(), BorderLayout.CENTER);
		jContentPane.add(getPnlBotoes(), BorderLayout.SOUTH);
	}
	return jContentPane;
}

private DefaultListModel getListModel() {
	if (listModel == null) {
		listModel = new DefaultListModel();
		for (int i = 0; i < 100; ++i) {
			listModel.addElement(String.format("Elemento %02d", i));
		}
	}
	return listModel;
}

private JList getLstList() {
	if (lstList == null) {
		lstList = new JList();
		lstList.setModel(getListModel());
		lstList.setFocusCycleRoot(true);
		lstList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		lstList.setSelectedIndex(0);

		// Como exemplo, fiz com que as teclas q e w funcionem como Up e
		// Down, respectivamente.
		lstList.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0),
				"up");
		lstList.getActionMap().put(
				"up",
				(Action) lstList.getActionForKeyStroke(KeyStroke
						.getKeyStroke(KeyEvent.VK_KP_UP, 0)));
		lstList.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0),
				"down");
		lstList.getActionMap().put(
				"down",
				(Action) lstList.getActionForKeyStroke(KeyStroke
						.getKeyStroke(KeyEvent.VK_KP_DOWN, 0)));
	}
	return lstList;
}

private JPanel getPnlBotoes() {
	if (pnlBotoes == null) {
		pnlBotoes = new JPanel();
		pnlBotoes.setLayout(new FlowLayout());
		pnlBotoes.add(getBtnOK(), null);
	}
	return pnlBotoes;
}

private JScrollPane getScpList() {
	if (scpList == null) {
		scpList = new JScrollPane();
		scpList.setViewportView(getLstList());
	}
	return scpList;
}

private void initialize() {
	this.setSize(320, 234);
	this.setContentPane(getJContentPane());
	this.setTitle("Exemplo de JList");
}

}[/code]

Note que “setSelectedItem”, conforme você deve ter percebido, não é a mesma coisa que mover com as setas.

Eu simplesmente copiei a mesma ação executada quando se usa a tecla de seta para cima para a tecla “q”.

Exercício - Veja que se você teclar Q com a tecla Shift apertada não vai funcionar (não vai mover a seta). Por que isso ocorre?

Outra dica: em muitos componentes do Swing, adicionar um KeyListener simplesmente não funciona do jeito que você quer. Muitas vezes você precisa mexer no ActionMap/InputMap (como fiz agora), ou então, em campos de entrada de dados, mexer no Document. No caso de um JComboBox, a situação é mais complicada ainda, e é por isso que é um pouco difícil fazer um AutoComplete que funcione.

Eu usei uma coisa que normalmente não recomendo, que é um DefaultListModel. Só fiz isso para simplificar o exemplo; normalmente eu usaria um ListModel baseado em um dos Models do GlazedLists ( http://publicobject.com/glazedlists )

sim testei o codigo acima ele ate funciona porem eu nao posse deichar o JList com foco e ai q entra o problema…

o codigo tem q funcionar com o …

em estado false.

OK, não tinha visto que a JList não tinha foco. Então:

package guj;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;

public class ExemploJList extends JFrame {

	private static final long serialVersionUID = 1L;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				ExemploJList thisClass = new ExemploJList();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				thisClass.setVisible(true);
			}
		});
	}

	private JButton btnOK = null;
	private JPanel jContentPane = null;
	private DefaultListModel listModel;
	private JList lstList = null;

	private JPanel pnlBotoes = null;

	private JScrollPane scpList = null;

	public ExemploJList() {
		super();
		initialize();
	}

	private JButton getBtnOK() {
		if (btnOK == null) {
			btnOK = new JButton();
			btnOK.setText("OK");
		}
		return btnOK;
	}

	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getScpList(), BorderLayout.CENTER);
			jContentPane.add(getPnlBotoes(), BorderLayout.SOUTH);
		}
		return jContentPane;
	}

	private DefaultListModel getListModel() {
		if (listModel == null) {
			listModel = new DefaultListModel();
			for (int i = 0; i < 100; ++i) {
				listModel.addElement(String.format("Elemento %02d", i));
			}
		}
		return listModel;
	}

	private JList getLstList() {
		if (lstList == null) {
			lstList = new JList();
			lstList.setModel(getListModel());
			lstList.setFocusCycleRoot(true);
			lstList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			lstList.setSelectedIndex(0);
			lstList.setFocusable(false);
			// Como exemplo, fiz com que as teclas q e w funcionem como Up e
			// Down, respectivamente.
			lstList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0),
					"up");
			lstList.getActionMap().put(
					"up", new AbstractAction() {
						@Override
						public void actionPerformed(ActionEvent e) {
							int selIndex = lstList.getSelectedIndex();
							if (selIndex > 0) 
								selIndex--;
							else
								selIndex = 0;
							lstList.setSelectedIndex (selIndex);
							lstList.ensureIndexIsVisible(selIndex); // aqui o pulo do gato
						}
					});
			lstList.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0),
					"down");
			lstList.getActionMap().put(
					"down",new AbstractAction() {
						@Override
						public void actionPerformed(ActionEvent e) {
							int selIndex = lstList.getSelectedIndex();
							if (selIndex < lstList.getModel().getSize()) 
								selIndex++;
							else
								selIndex = lstList.getModel().getSize() - 1;
							lstList.setSelectedIndex (selIndex);
							lstList.ensureIndexIsVisible(selIndex); // aqui o pulo do gato
						}
					});
		}
		return lstList;
	}

	private JPanel getPnlBotoes() {
		if (pnlBotoes == null) {
			pnlBotoes = new JPanel();
			pnlBotoes.setLayout(new FlowLayout());
			pnlBotoes.add(getBtnOK(), null);
		}
		return pnlBotoes;
	}

	private JScrollPane getScpList() {
		if (scpList == null) {
			scpList = new JScrollPane();
			scpList.setViewportView(getLstList());
		}
		return scpList;
	}

	private void initialize() {
		this.setSize(320, 234);
		this.setContentPane(getJContentPane());
		this.setTitle("Exemplo de JList");
	}

} // @jve:decl-index=0:visual-constraint="10,10"

A janela em si tem de ter o foco (isso é porque janelas sem foco não recebem eventos de teclado). Mas o JList não precisa ter o foco.

Repare, ao rodar o exemplo, que o foco continua sempre no botão OK, mesmo que se tecle q ou w. Obviamente, se você teclar um espaço, vai ativar o botão OK, como esperado.

ok vou implementar este exemplo no meu codigo pra ver se funciona pq eu testei esse exemplo q vc me passo e funciono certinho agora quero ver se vai funcionar no meu codigo…

Ok testei aqui deu certinho… muito obrigado pela ajuda… e meio chato ser iniciante e ter q ficar perguntando… mais em breve espera poder estar ajudando os outros aki no forum tmb…

=]

so mais uma duvida tem alguma maneira de centralizar o texto da JList?

No meu “technical debt” está, por exemplo, escrever no meu blog sobre todas as formas de não usar um KeyListener.
Até agora não escrevi, por exemplo, como é que se usa um “try with resources” com um java.sql.Connection.
Como vocês devem ter aprendido na marra, o comportamento de teclas com os componentes do Swing raramente pode ser customizado usando-se um mero KeyListener.