Certo, e umas dicas para a utilização:
Se você sabe que a tabela não vai ter nenhuma edição em suas células (como o caso dessa) você nem precisa implementar o método setValueAt
se quiser.
E adicione estes métodos que pode facilitar o manejamento da List
do TableModel:
// Adiciona uma lista à lista atual
public void addListBeans(List<BeanBanco> bean) {
// Adiciona os registros
linhas.addAll(bean);
// Notifica a mudança
fireTableDataChanged();
}
// Remove todos os registros
public void clearBeans() {
linhas.clear();
// Notifica a mudança
fireTableDataChanged();
}
// Retorna a list referente as linhas da tabela
public List<ContasReceber> getListBeans() {
return dados;
}
Bom, quanto a seleção na linha da tabela, as duas tabelas (da tela A e B) apresentam os mesmos dados correto? Utilizam o mesmo Model mostrando as ContasReceber
?
E uma coisa, a sua JTable
tem algum sorting pra você clicar por exemplo na coluna e reordenar os dados e tal?
Obrigado pelas dicas!
Sim as duas tabelas contem os mesmos dados, porém em telas diferentes. Utilizam o mesmo model.
Tem um sorter também:
public void ordenarColunas() {
tbContasReceber.setModel(tableModel);
tbContasReceber.setRowSorter(new TableRowSorter(tableModel));
}
Certo, depende um pouco do padrão que você está adotando mas pode ser feito algo como:
Na tela A você tem uma JTable
onde você você clica para abrir a tela B, neste momento você pega o Objeto selecionado na tabela e passa para a tela B em seu construtor:
// Já que pode ter um sorter primeiro pega a linha selecionada na tela
// (que pode estar reordenada então diferente da List do TableModel)
int indexView = table.getSelectedRow();
// Converte o index de View para Model, fazendo a conversão da Visão
// que pode ter sido reordenada na camada View da JTable para a List
// na camada Model no TableModel (List só é reordenada na View)
int indexModel = table.convertRowIndexToModel(indexView);
// Recebe a List do seu TableModel
List<ContasReceber> lisContas = table.getModel().getListBeans();
// Pega o Objeto referente à seleção, com o index já convertido
ContasReceber contaReceber = (ContasReceber) lisContas.get(indexModel);
Então você passa este objeto que você quer deixar selecionado na próxima tela no seu construtor (Faz o construtor desta forma na classe do frame, claro) se você quiser você pode utilizar Listener para transmitir esse dado, algum Design Patter que esteja utilizando… O importante é a TelaB ter acesso à este objeto:
FrameB frameB = new FrameB(contaReceber);
frameB.setVisible(true);
E no seu código então na tela B, após popular a sua tabela, vem a parte que você requisitou, de nesta tabela populada deixar selecionada a Linha com o mesmo objeto selecionado na tela A.
Então na tela B:
// Recebe a List do seu TableModel
List<ContasReceber> lisContas = table.getModel().getListBeans();
// Recebe o index onde o Objeto é correspondente ao mesmo da tabela A.
// Objeto este que foi recebido no construtor
int indexModel = listContas.indexOf(contaReceber);
// Converte o index de Model para a View caso a JTable tenha feito algum Sorting
int indexView = table.convertRowIndexToView(indexModel);
// Coloca a seleção na JTable passando o range inicial e final (o mesmo já que é só uma linha)
table.setRowSelectionInterval(indexView, indexView);
// E um extra, caso o item esteja muito abaixo por ser uma lista grande ou a tela pequena
// ele vai selecionar normalmente, mas o usuário vai ter que fazer o Scroll para ir até a
// linha selecionada na JTable caso queira visualizar a linha selecionada explicitamente,
// então o código abaixo já faz o Scroll automaticamente deixando a seleção visível
table.scrollRectToVisible(new Rectangle(table.getCellRect(indexView, 0, true)));
Bom acho que é isso, testa e vê se da certo da forma que você queria.
To errando em alguma coisa, não está encontrando a linha
Segue o que eu fiz:
Chamo ao clicar na tabela A:
public static Object index;
public void setRow() {
tbContasReceber.setModel(tableModel);
int indexView = tbContasReceber.getSelectedRow();
int indexModel = tbContasReceber.convertRowIndexToModel(indexView);
List<ContasReceber> lisContas = tableModel.getListBeans();
ContasReceber contaReceber = (ContasReceber) lisContas.get(indexModel);
index = contaReceber;
System.out.println("Verificar setRow: "+index);
}
Chamo ao ativar a tela que contem a tabela B:
public void getRow() {
Object ind = tCR.index; //tCR --> Tela que contém tabela A
System.out.println("Verificar getRow: "+ind);
tbContas.setModel(tableModel);
List<ContasReceber> lisContas = tableModel.getListBeans();
int indexModel = lisContas.indexOf(ind);
int indexView = tbContas.convertRowIndexToView(indexModel);
tbContas.setRowSelectionInterval(indexView, indexView);
tbContas.scrollRectToVisible(new Rectangle(tbContas.getCellRect(indexView, 0, true)));
}
Erro gerado:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Row index out of range
at javax.swing.JTable.boundRow(JTable.java:2143)
at javax.swing.JTable.setRowSelectionInterval(JTable.java:2166)
at TelasFinanceiro.TelaReceber.getRow(TelaReceber.java:768)
at TelasFinanceiro.TelaReceber.formWindowActivated(TelaReceber.java:373)
at TelasFinanceiro.TelaReceber.access$000(TelaReceber.java:52)
at TelasFinanceiro.TelaReceber$1.windowActivated(TelaReceber.java:107)
at java.awt.Window.processWindowEvent(Window.java:2066)
at javax.swing.JFrame.processWindowEvent(JFrame.java:305)
at java.awt.Window.processEvent(Window.java:2013)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:995)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:488)
at java.awt.Component.dispatchEventImpl(Component.java:4760)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.SentEvent.dispatch(SentEvent.java:70)
at java.awt.DefaultKeyboardFocusManager$DefaultKeyboardFocusManagerSentEvent.dispatch(DefaultKeyboardFocusManager.java:217)
at java.awt.DefaultKeyboardFocusManager.sendMessage(DefaultKeyboardFocusManager.java:244)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:366)
at java.awt.Component.dispatchEventImpl(Component.java:4760)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.SequencedEvent.dispatch(SequencedEvent.java:128)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Parece que quando você está falando pra ele colocar a seleção na sua tabela, ela está vazia, a ideia era abrir o seu frame primeiro populando a tabela e então colocar a seleção nela. Em que momento exatamente ocorre o erro? E você tem algum Listener ou algo do tipo que pode implicar neste fluxo invocando este método?
Altera o código deixando igual abaixo e vê se continua com o mesmo erro:
public void getRow() {
Object ind = tCR.index; //tCR --> Tela que contém tabela A
System.out.println("Verificar getRow: "+ind);
tbContas.setModel(tableModel);
List<ContasReceber> lisContas = tableModel.getListBeans();
int indexModel = lisContas.indexOf(ind);
int indexView = tbContas.convertRowIndexToView(indexModel);
if (tbContas.getRowCount() > 0) {
tbContas.setRowSelectionInterval(indexView, indexView);
tbContas.scrollRectToVisible(new Rectangle(tbContas.getCellRect(indexView, 0, true)));
}
}
Realmente estava chamando no momento errado
Chamei após popular a tabela, o erro sumiu, mas não funcionou, não selecionou a linha desejada 
Coloquei o ‘getRow()’ aqui:
public void readClientes() {
try {
String nome = lbNome.getText();
tbContas.setModel(tableModel);
ContasReceberDAO dao = new ContasReceberDAO();
for (ContasReceber c : dao.readCliente(nome)) {
String codigoCliente = String.valueOf(c.getCodigoCliente());
String cheque = c.getFormaPagamento();
if (!"Cheque !".equals(cheque)) {
tableModel.addRow(c);
}
lbCodigo.setText(codigoCliente);
}
getRow();
} catch (Exception e) {
}
}
Entranho… Não deu nenhum erro?
Eu não entendi muito bem o padrão que você adotou e nem o fluxo do programa. Este método readClientes
ele pertence / é executado na classe da tela B?
E por que você está guardando o ContaReceber em uma variável static
e de tipo Object
e não ContasReceber
?
É melhor postar o código completo pra eu entender melhor o que está acontecendo.
Não apresenta erros
Tela A:
public class TelaContaReceber extends javax.swing.JFrame {
}
Tela B:
public class TelaReceber extends javax.swing.JFrame {
}
Altera o construtor da sua “TelaB” e adiciona mais um atributo, deixando assim:
private ContasReceber contaReceber;
public TelaReceber(ContasReceber contaReceber) {
initComponents();
this.setLocationRelativeTo(null);
redefinirColuna();
tipoMovimentacao = "Receita";
this.contaReceber = contaReceber;
}
Então naquele método “getRow” deixa assim:
public void getRow() {
ContasReceber contaReceber = this.contaReceber;
System.out.println("Verificar instancia: " + contaReceber.getCodigoCliente());
tbContas.setModel(tableModel);
List<ContasReceber> listContas = tableModel.getListBeans();
if (listContas.contains(contaReceber)) {
System.out.println("tem a conta pra selecionar");
int indexModel = listContas.indexOf(contaReceber);
int indexView = tbContas.convertRowIndexToView(indexModel);
tbContas.setRowSelectionInterval(indexView, indexView);
tbContas.scrollRectToVisible(new Rectangle(tbContas.getCellRect(indexView, 0, true)));
}
}
Então lá na “TelaA” na hora de instancia a “TelaB” você passa o Objeto pelo construtor, e apaga aquela variável static que tinha antes e muda o retorno do método pra ContasReceber:
// Apaga esta variavel: public static ContasReceber index;
public ContasReceber setRow() {
tbContasReceber.setModel(tableModel);
int indexView = tbContasReceber.getSelectedRow();
int indexModel = tbContasReceber.convertRowIndexToModel(indexView);
List<ContasReceber> lisContas = tableModel.getListBeans();
ContasReceber contaReceber = (ContasReceber) lisContas.get(indexModel);
return contaReceber;
}
E lá no if onde você invoca o método faz assim:
if (evt.getClickCount() > 1 && !fPagamento.equals("Cheque !")) {
ContasReceber contaReceber = setRow();
TelaReceber telaReceber = new TelaReceber(contaReceber);
telaReceber.setVisible(true);
try {
String id = tableModel.getValueAt(index, 0).toString();
String cliente = tableModel.getValueAt(index, 1).toString();
String formaPagamento = tableModel.getValueAt(index, 6).toString();
telaReceber.lbNome.setText(cliente);
telaReceber.cbFormaPagamento.setSelectedItem(formaPagamento);
telaReceber.lbCliente.setText(selec + ":");
IdContaReceber = id;
} catch (Exception e) {
}
}
Meu amigo, não deu certo ainda
Não seleciona linha nenhuma e não aparece erros
Vou desistir dessa implementação, já to quase destruindo a tela desse PC
Se tiveres mais alguma ideia…
Mas já agradeço a ajuda e o empenho
kkkkk tranquilo, teria que debugar pra ver o que está acontecendo…
Eu coloquei dois PrintLn ali, quando ele printou no console o ID da ContaReceber é realmente o ID da conta que você quer colocar a seleção?
E ele escreveu no console a frase “tem a conta pra selecionar”?
Senão, ele nem chegou no código que seleciona a linha.
A ID está pegando corretamente
No console não aparece a frase “tem a conta pra selecionar”
No debug ele não ta chegando no código que seleciona a linha mesmo
Certo, se ele está chegando até aquele ponto e tem um Objeto preenchido pra comparar, a gente pode sobrescrever o método Equals, ou mais fácil, transformar a List em Stream e filtrar por algum atributo de identificação.
Então pra comparar, a sua classe ContaReceber tem um atributo único de ID correto? É um Integer? Posta a declaração da sua classe ContaReceber pra eu ver.
E qual versão do Java você está utilizando? Java 8+?
Java 8
public class ContasReceber {
}
Certo, é do tipo primitivo int. Então altera o método “getRow” que coloca a seleção na JTable e deixa ele assim:
public void getRow() {
ContasReceber contaReceber = this.contaReceber;
tbContas.setModel(tableModel);
List<ContasReceber> listContas = tableModel.getListBeans();
// Transforma em Stream, filtra e retorna o Objeto que tem o mesmo ID
// Se não tem um objeto com o mesmo ID retorna null
ContasReceber contaMatch = listContas.stream()
.filter(conta -> conta.getIdContasReceber() == contaReceber.getIdContasReceber()).findFirst()
.orElse(null);
if (contaMatch != null) {
int indexModel = listContas.indexOf(contaMatch);
int indexView = tbContas.convertRowIndexToView(indexModel);
tbContas.setRowSelectionInterval(indexView, indexView);
tbContas.scrollRectToVisible(new Rectangle(tbContas.getCellRect(indexView, 0, true)));
}
}
Pow cara!
Nem acredito que deu certo, já estava desistindo…kkkkk
Muito bom!
Só mais uma dúvida, a tabela na tela B vem sempre carregada com o scroll na metade, não fica no local onde ocorreu a seleção, tem como arrumar isso?
Tem essa linha no código, mas não tá legal:
tbContas.scrollRectToVisible(new Rectangle(tbContas.getCellRect(indexView, 0, true)));
Cara, se não me engano com essa linha de código era pra fazer o scroll automaticamente até que a linha selecionada fique visível na tela.
A seleção não está ficando visível na tela?
Pode ser que algum Listener ou Sorter está fazendo algo que você não percebeu e alterando este comportamento esperado
Consegui, jogue a linha para o ‘formWindowActivated’…Funcionou beleza!!
Obrigado pela ajuda e pelas dicas!