Pessoal, já li alguns tutoriais e posts aqui do fórum, mas ainda não consegui desenhar checkboxes nas linhas pares da primeira coluna da tabela. As malditas aparecem em todas as linhas.
Meu model:
Acho que você terá que fazer o seu próprio CustomCellEditor e CustomCellRenderer. E daí xunxar um pouquinho as coisas.
Faça um CustomCellRenderer que:
1.1. Teste o tipo do objeto sendo editado.
1.2. Se for um Boolean, usa o CellRenderer de Boolean.
1.3. Caso contrário, usa o DefaultCellRenderer;
Faça o mesmo para o CellEditor;
Altere o CellEditor e o CellRenderer da coluna um para os criados acima;
Faça o seu TableModel retornar um Boolean para as colunas com CheckBox e uma string vazia para as sem. Também faça ele retornar que as linhas sem o checkbox não são editáveis.
Nas linhas ímpares não deve aparecer nada. Lembrando que isso é apenas para a primeira coluna, nas demais aparecerão String, Long, Double, etc.
Do 1 ao 3 vou ter que olhar essas classes que não conheço.
Como fazer isso? Assim, não vai.
public Object getValueAt(int row, int col) {
if (col == 0 && row % 2 != 0)
return ""; // ClassCastException
return dados[row][col];
}
Retornar null continua desenhando as checkbox. O não-editável nas ímpares já está funcionando.
Vai continuar dando ClassCastException enquanto você não alterar o Renderer e o Editor. Eles é que tentam fazer cast do valor das colunas Boolean para o tipo Boolean. Quando você fizer o seu próprio Renderer, você só vai delegar para o Renderer de boolean default se o tipo do valor for efetivamente boolean. Caso contrário, você vai delegar para o DefaultRenderer, que trata strings. O mesmo pro editor.
É isso? Como delegar para o Renderer de boolean default?
Outra coisa: eu adiciono ele e o CellEditor apenas na primeira coluna ou como default da tabela?
private class ResultadosTableRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
if (value instanceof Boolean) {
// return ???
}
return table.getCellRenderer(row, col).getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
}
};
Adicione o renderer só para a coluna. Pensando um pouco, é provável que você nem tenha que fazer a mesma coisa para o CellEditor.
Basta definir o CellEditor de Boolean para a coluna também. Afinal, as colunas sem Booleans dentro não são editáveis. E o CellEditor só entra em ação quando o usuário consegue editar a célula.
Nem tanto… quando não era Boolean e estava na coluna zero, ele chamava o próprio Renderer recursivamente até estourar a pilha
Usando o Renderer default de String (aparentemente) deu certo.
[code]
private class ResultadosTableRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
if (value instanceof Boolean)
return table.getDefaultRenderer(Boolean.class).getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
};[/code]
Alguns pontos:
1- Não defini CellEditor.
2- Acho meio tosco um clique em qualquer local da célula ativar o checkbox. Tem algum jeito simples de resolver isso ou vou precisar escutar eventos de mouse? Em caso contrário, posso deixar a coluna estreita para isso não ficar muito perceptível.
3- Para definir ações dos checkboxes, é preciso implementar TableModelListener?
Bem, esse é o comportamento padrão da maior parte das tabelas com checks.
Não tem um jeito simples de fazer isso, e checar eventos do mouse não é uma boa também. Você pode deixar a coluna mais estreita usando o método setWidth do TableColumn (a JTable, q eu me lembre, tem um método para retornar o TableColumn. Na pior das hipóteses, consulte o TableColumnModel dela).
Via de regra, não é uma boa prática alterar o comportamento padrão dos componentes do Swing, a menos que existem ganchos especificamente para isso. Além de complicado, é sujeito a erros, difícil de manter e ainda não respeita os vários look&feels (e se for respeitar, vai ser mais difícil ainda).
Que tipo de ações? Se forem ações que atuem sobre os próprios dados do model, não, você pode fazer isso no model, desde que propague o evento TableRowChanged na linha em questão. Caso contrário, sim, implemente o listener. Uma outra alternativa é implementar um dos listeners da própria JTable.
Viajei.
Não preciso de ação alguma. Na verdade, só preciso posteriormente saber quais são as linhas checadas.
for (int i = 0; i < model.getRowCount(); i += 2) {
model.getValueAt(i, 0);
// codigo
}
O único problema que restou é que eu gostaria que algumas células em colunas Double ficassem vazias. Antes, bastava eu setar a célula null, mas, desde que implementei meu próprio TableModel, isso lança um NullPointerException.