Olá pessoal
Tenho um tabela “A” que contém uma lista de contas a receber, vindas do banco mysql.
Ao clicar em uma linha abre-se uma tela para realizar o recebimento da conta.
Na tela de recebimento faço uma consulta ao banco e carrego todas as contas do cliente selecionado em uma tabela “B”.
O que eu quero:
Ao abrir a tela de recebimento quero que já venha selecionado a linha na tabela “B” correspondente ao que eu cliquei na tabela “A”.
Exemplo:
Tabela A:
Nome | Conta | Valor | vencimento
João | Venda| 1,00 | 01/01/2019
José | Venda| 2,00 | 02/01/2019
João | Venda| 5,00 | 05/01/2019 <<----Linha selecionada
Maria | Venda| 3,00 | 05/01/2019
João | Venda| 8,00 | 06/01/2019
Tabela B: (Carrego todas as contas relacionadas ao João)
João | Venda| 1,00 | 01/01/2019
João | Venda| 5,00 | 05/01/2019 <<----Quero que essa linha venha selecionada
João | Venda| 8,00 | 06/01/2019
Alguém pode me ajudar?
Código para selecionar a linha na tabela “A”:
if (evt.getClickCount() > 1) {
TelaReceber telaReceber = new TelaReceber();
telaReceber.setVisible(true);
try {
int index = tbContasReceber.getSelectedRow();
DefaultTableModel modelo = (DefaultTableModel) tbContasReceber.getModel();
String id = modelo.getValueAt(index, 0).toString();
String cliente = modelo.getValueAt(index, 1).toString();
String formaPagamento = modelo.getValueAt(index, 6).toString();
telaReceber.lbNome.setText(cliente);
telaReceber.cbFormaPagamento.setSelectedItem(formaPagamento);
telaReceber.lbCliente.setText(selec + ":");
IdContaReceber = id;
} catch (Exception e) {
}
}
Código carregar tabela “B”:
try {
String nome = lbNome.getText();
DefaultTableModel modelo = (DefaultTableModel) tbContas.getModel();
modelo.setNumRows(0);
ContasReceberDAO dao = new ContasReceberDAO();
for (ContasReceber c : dao.readCliente(nome)) {
Date dt = c.getVencimento();
double vl = c.getValor();
String codigoCliente = String.valueOf(c.getCodigoCliente());
DateTimeFormatter formatadorData = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDateTime localDateTime = dt.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
String d = formatadorData.format(localDateTime);
Locale l = new Locale("pt", "BR");
NumberFormat nf = NumberFormat.getCurrencyInstance(l);
String v = nf.format(vl);
modelo.addRow(new Object[]{
c.getIdContasReceber(),
c.getConta(),
c.getDescricao(),
d,
v
});
lbCodigo.setText(codigoCliente);
}
} catch (Exception e) {
}
}
DefaultTableModel aí complica heim amigo…
Cria um TableModel aí pra sua classe e objetos pra representar estas entidades, afinal são “ContasReceber” estes objetos listados na tabela ou não?
Aí você pega o index da ocorrência do objeto que você quer na List
do seu TableModel e coloca a seleção na JTable
pra esse item desejado.
Sim, são contas a receber
Então, sabia que ia pegar essa do DefaultTableModel, mas sou iniciante, falta aprender muito ainda. Não sei criar um TableModel 
Da forma que eu to fazendo não tem jeito?
Olha, não digo que não tem como, precisaria fazer alguns testes e ver o funcionamento… Mas alguma solução que eu pensaria no momento com certeza seria mais complicado do que criar um TableModel que é algo bem simples, tem um roteirinho pra seguir e da até pra dar um Ctrl C e Ctrl V no código lá e alterar basicamente só a Classe que ele manipula e alguns parâmetros básicos…
Só pesquisar no Google que tem tutorial explicando linha por linha, como este:
Obrigado Daniel
Vou dar uma estudada no TableModel então
Valeu a dica!
Consegui criar um AbstractTableModel
Realmente não é difícil, basta ler um pouquinho
Mas ainda estou na duvida de como fazer a seleção na outra tabela
Segue o código da minha TableModel:
public class TableModelContasReceber extends AbstractTableModel {
}
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