Estou desenvolvendo uma aplicaçãozinha usando swing e um banco mysql.
Em determinado momento, tenho uma JTable, inserida em um JScrollPane, q mostra os dados vindos do banco.
Para isso, utilizei uma TableModel (DefaultTableModel) e linkei ela com a table. Até aí, tudo OK.
Agora vem minha dúvida: kero permtir q o usuário altere os dados na JTable e que isso se reflita no banco (e claro na TableModel, né?? ).
Tentei usar o InputMethodTextChanged, mas num consegui. Na verdade naum entendi direito esse evento. Tentei colocá-lo tbém em JTextField, mas parece q ele nunca é disparado… :!: :?:
Vc quer atualizar o banco em tempo real ( assi mque termina de editar na JTable vá para o banco )?? Ou deixar um botão estilo “Salvar” para salvar no banco as alterações ?
Tenho diversos casos onde vou precisar usar esse recurso. em alguns casos, kero que vá direto para o banco (mas para isto utilizo os métodos setXXXX pra cada atributo que tenho. o objeto é responsável por fazer o mapeamento para o banco). Em outros, terei o botãozinho estilo “salvar”.
O que realmente procuro saber é qual evento utilizar para isto.
Qualquer dos dois exemplos que vc puder me ajudar são válidos.
Qdo for online, acho que um listener no TableModel pra escutar as alterações ocorridas, resolve. Pois toda vez que alguem digitar um valor na JTable e confirmar o valor ( stopCellEditing ) esse listener vai disparar, pois é qdo a JTable atualiza o TableModel, e é onde vc deve pegar o valor atualizado e atualizar no banco ( mas não acho muito legal, pq toda hora vc vai fazer update no banco = muito trafego de rede ).
Qdo for disparado o update por um botão, simples: pra cada alteração na JTable, vc pode marcar a linha alterada ( ou marcando direto na linha, ou adicionando num array ) e depois, qdo clicado no botão para salvar, leia esse array, salvando as linhas da TableModel que estão neste array.
ok… a parte teórica entendi blz…
mas sinceramente gostaria de ver algum exmeplo msm… tem algum link, algum lugar onde posso achar uns exemplos?
por exemplo: tá me parecendo q a table num tá alterando a tableModel.
alguma manha especial pra fazer isso?? só alterei a propriedade da table, permitindo q as células sejam alteradas… consigo alterar o conteúdo… aparece na table, td ok… porém num vejo a alteração na tableModel… nem consigo usar o evento InputMethodTextChanged (tá errado isso?)
só como teste: qdo for alterada alguma célula na Table, escrever o novo valor da célula em uma jTextField.
pra segunda solução: como marcar as linhas da talbe q foram alteradas? aliás, seria até melhor marcar a(s) célula(s) alteradas, assim só altero no banco o(s) campo(s) com modificações.
Infelizmente, não está tudo ok. Ele cometeu um erro fatal, usou o DefaultTableModel. Isso deu um grau de controle perto do zero no JTable. Também tem a desvantagem de ser mais difícil de usar, duplicar dados e ser desnecessáriamente sincronizado, prejudicando a performance em tabelas maiores.
Pare um tempo e estude como um TableModel personalizado funciona. Cada minuto “perdido” será mais do que compensado.
Realmente nao gosto do defaultaTableModel pois tenho a sensação que torna uma aplicação GUI demasiado lenta! Por isso implementei o meu próprio tablemodel.
Gostaria de pedir alguns documentos a ler sobre listener, visto ser a parte em que sinto mais dificuldade. :S
[code]getMyTableModel().addTableModelListener(new TableModelListener(){
public void tableChanged(TableModelEvent e){
System.out.println("MUDEI");
}
});[/code]
Este é o meu codigo, mas este listener só funciona em caso de DELETE ou INSERT, não funciona em caso de update!
Esta minha tabela tem todas as marcas de carros, e editarem uma marca de carro na minha jtable eu quero fazer determinada acção! Mas não estou a conseguir tentar o update :?
Agradeço muito a sua ajuda, mas jáfiz o codigo igual al seu e ele não reage ao UPDATE :? é como se o UPDATE não fgizesse disparar o evento! já não sei que faça mais :?
[code]
public class MyTableModel extends AbstractTableModel{
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] nameCol = {"ID MARK", "MARK"};
private ArrayList<Mark> list;
public MyTableModel(){};
public MyTableModel(ArrayList<Mark> list){
this.list = list;
}
@Override
public int getColumnCount() {
return nameCol.length;
}
@Override
public int getRowCount(){
if(list==null) return 0;
return list.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Mark m = list.get(rowIndex);
switch(columnIndex){
case 0: return m.getIdMark();
case 1: return m.getMark();
}
return null;
}
public void addRow(Mark m){
list.add(m);
fireTableRowsInserted(list.size()-1, list.size()-1);
}
public void removeRow(int index){
list.remove(index);
fireTableRowsDeleted(index, index);
}
@Override
public String getColumnName(int columnIndex){
return nameCol[columnIndex];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex){
return true;
}
}[/code]
Este é o meu código e realmente ele não implementa nada sobre os listener e eu não digo que tenho de alterar, na verdade é que se editar um celula e carregar no enter o valor mantém-se igual ao que tinha antes de ter começado a escrever. Sendo assim acho que não sei como fazer o tablemodel se modificar. :?
O AbstractTableModel já implementa os métodos relacionados ao TableModelListener. Cabe a nós apenas notificar a mudança usando os métodos “fire…”, como você fez nos métodos addRow e removeRow.
Agora que entendi seu problema, você quer digitar as alterações diretamente na célula certo? Para isso não precisa do TableModelListener.
Quando alguma alteração é feita no conteúdo da célula, o método “setValueAt” do TableModel é invocado. AbstractTableModel implementa este método para não fazer nada, por isso não está havendo modificação. Portanto, você deve implementar o método, segue um exemplo:
[code] @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Mark m = list.get(rowIndex); // Carrega o item da linha que deve ser modificado
switch (columnIndex) {
case 0: // modifica o item da coluna 0
m.setIdMark(aValue);
case 1: // modifica o item da coluna 1
m.setMark(aValue);
default:
throw new IndexOutOfBoundsException("columnIndex out of bounds");
fireTableCellUpdated(rowIndex, columnIndex); // Notifica a atualização da célula
}[/code]
[quote=Eric Yuzo]O AbstractTableModel já implementa os métodos relacionados ao TableModelListener. Cabe a nós apenas notificar a mudança usando os métodos “fire…”, como você fez nos métodos addRow e removeRow.
Agora que entendi seu problema, você quer digitar as alterações diretamente na célula certo? Para isso não precisa do TableModelListener.
Quando alguma alteração é feita no conteúdo da célula, o método “setValueAt” do TableModel é invocado. AbstractTableModel implementa este método para não fazer nada, por isso não está havendo modificação. Portanto, você deve implementar o método, segue um exemplo:
[code] @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Mark m = list.get(rowIndex); // Carrega o item da linha que deve ser modificado
switch (columnIndex) {
case 0: // modifica o item da coluna 0
m.setIdMark(aValue);
case 1: // modifica o item da coluna 1
m.setMark(aValue);
default:
throw new IndexOutOfBoundsException("columnIndex out of bounds");
fireTableCellUpdated(rowIndex, columnIndex); // Notifica a atualização da célula
}[/code][/quote]
Voce é genial!! Até acertou nos nome dos meus metodos
Sim, realmente percebi o meu problema, no fundo o setValueAt funciona da mesma forma que o getValueAt, e como não o tinha implementado o table model não alterava!
Relativamente ao facto de ter um listener. Essa questão vem porque eu queria ter uma tabela com para fazer “orçamentos” e adicionava produtos a tabela e caso fosse necessário mudar o valor ao preço era só alterar na JTable e automaticamente era recalculado o valor total do orçamento. Deu para entender o que pretendo?
Já agora um muito obrigado a todos que participaram neste tópico de ajuda! Não espera ter tanta ajuda! Muito obrigado!! :oops:
Depois de ter redefinido o metodo setValeuAt, o meu listener já passou a reagir ao update também! Está mesmo perfeito!
Agora de seguida vou tentar incluir uma JCheckBox na Jtable.
Se tudo correr bem vou definitivamente passar para a programação em ECLIPSE com VISUAL EDITOR, para me libertar do netbeans :?