3

I found sample with updating data, but it uses DefaultTableModel. When I created my own TableModel and my own data class, when I add data into JTable it doesn't update.

How do I add a listener to my TableModel?

Here is my code:

package by;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.LinkedList;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
public class DialogEg {
   private static void createAndShowGui() {
      MainWin mainPanel = new MainWin();
      JFrame frame = new JFrame("DialogEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }
   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
class MainWin extends JPanel {
   private String[] COL_NAMES = { "Last Name", "First Name" };
   //private DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0);
   private MyTableModel model = new MyTableModel();
   private JTextField lastNameField = new JTextField(15);
   private JTextField firstNameField = new JTextField(15);

   public MainWin() {
      final JPanel dataPanel = new JPanel();
      dataPanel.add(new JLabel("Last Name:"));
      dataPanel.add(lastNameField);
      dataPanel.add(Box.createHorizontalStrut(15));
      dataPanel.add(new JLabel("First Name:"));
      dataPanel.add(firstNameField);
      JPanel btnPanel = new JPanel();
      btnPanel.add(new JButton(new AbstractAction("Add Name") {
         @Override
         public void actionPerformed(ActionEvent arg0) {
            lastNameField.setText("");
            firstNameField.setText("");
            int result = JOptionPane.showConfirmDialog(MainWin.this, dataPanel,
                  "Enter Name", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
            if (result == JOptionPane.OK_OPTION) {
               String lastName = lastNameField.getText();
               String firstName = firstNameField.getText();
               Object[] dataRow = new String[] { lastName, firstName };
               //model.addRow(dataRow);
               Person person = new Person();
               person.setFirstName(firstName);
               person.setLastName(lastName);
               model.addElement(person);
               model.fireTableDataChanged();
            }
         }
      }));
      setLayout(new BorderLayout());
      JTable jtable = new JTable(model);
      //new JTable(model)
      jtable.setModel(model);
      add(new JScrollPane(jtable), BorderLayout.CENTER);
      add(btnPanel, BorderLayout.SOUTH);
   }
}
class MyTableModel extends AbstractTableModel {
    private String[] columnNames = {
            "Last name",
            "First name"
    };
    //private LinkedList<Person> data = new LinkedList<Person>();
    private LinkedList<Person> data = new LinkedList<Person>();
    public int getColumnCount() {
        return columnNames.length;
    }
    public int getRowCount() {
        return data.size();
    }
    public String getColumnName(int col) {
        return columnNames[col];
    }
    public Object getValueAt(int row,int col) {
        switch(col) {
        case 0: {
            return data.get(col).getLastName();
        }
        case 1: {
            return data.get(col).getFirstName();
        }
        default:
            return "";
        }
    }
    public void addElement(Person person) {
        data.add(person);
    }
    public void fireTableDataChanged() {

    }
}
class Person {
    String last_name;
    String first_name;
    public Person() {
    }
    public void setLastName(String l_name) {
        last_name = l_name;
    }
    public void setFirstName(String f_name) {
        first_name = f_name;
    }
    public String getLastName() {
        return last_name;
    }
    public String getFirstName() {
        return first_name;
    }
}

Edit2

Here i use method addElement:

 public void actionPerformed(ActionEvent arg0) {
    lastNameField.setText("");
    firstNameField.setText("");
    int result = JOptionPane.showConfirmDialog(MainWin.this, dataPanel,
          "Enter Name", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
    if (result == JOptionPane.OK_OPTION) {
       String lastName = lastNameField.getText();
       String firstName = firstNameField.getText();

       Person person = new Person();
       person.setFirstName(firstName);
       person.setLastName(lastName);
       //here i use add element 
       model.addElement(person);
    }
 }

There is my table model:

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = {
            "Last name",
            "First name"
    };
    //private LinkedList<Person> data = new LinkedList<Person>();
    private LinkedList<Person> data = new LinkedList<Person>();
    public int getColumnCount() {
        return columnNames.length;
    }
    public int getRowCount() {
        return data.size();
    }
    public String getColumnName(int col) {
        return columnNames[col];
    }
    public Object getValueAt(int row,int col) {
        switch(col) {
        case 0: {
            return data.get(col).getLastName();
        }
        case 1: {
            return data.get(col).getFirstName();
        }
        default:
            return "";
        }
    }

    public void addElement(Person person) {
        int firstRow = data.size() - 1;
        int lastRow = firstRow;
        fireTableRowsInserted(firstRow, lastRow);
    }
}

When i added any information, but it doesn't updated. Where i have to put this method for right data updating in jtable?

veinhorn
  • 2,363
  • 6
  • 21
  • 33

1 Answers1

4

You're doing two things that are very dangerous:

  • You're overriding fireTableDataChanged() and giving it an empty method body thereby bypassing all the magic that the super's method contains and making it essentially a worthless method,
  • and you're not calling any of the fireXXXChanged() methods after changing the model's data.

I recommend that you do the exact opposite:

  • Don't override fireTableDataChanged()
  • Call the fireXXX() methods when you change data.

For example:

public void addElement(Person person) {
   data.add(person);
   int firstRow = data.size() - 1;
   int lastRow = firstRow;
   fireTableRowsInserted(firstRow, lastRow);
}

// public void fireTableDataChanged() {
//
// }

As an aside: why do you want to add a listener to the JTable or its TableModel?

Edit 2
You state:

I thought that i have to implement one of the firexxx method.

The reason that your class extends the AbstractTableModel class rather than implementing the TableModel interface is to get all the goodies that the AbstractTableModel class has to offer, including its fireXXX(...) methods. They're already wired to notify any JTables that use the model that the data has changed. If you override them, and especially if you override them and don't call any of the super methods, you've broken this helpful code and it will no longer work.

As for LinkedList, i wanted to try use another collection(no array like in all samples).

Since you will usually want to access the data in a random way, I think you'd get more money out of an ArrayList. Regardless, the collection variable should probably be of List interface type so you can change the data type of the collection object as needed.

I don't understand why when i use your implementation it doesn't work.

If you say something "doesn't work" and you don't explain how or why it's not working, what errors you may be seeing, and without showing your code implementation, you tie our hands and prevent us from being able to help you effectively. If you need our help, consider giving us enough information to allow us to understand your problem. This will include showing us any changes to your code, showing any compilation errors or exception messages, and describing in detail the specifics of your problems.

Edit 3
In your most recent code iteration, your addElement method does everything but add an element!

public void addElement(Person person) {
    int firstRow = data.size() - 1;
    int lastRow = firstRow;
    fireTableRowsInserted(firstRow, lastRow);
}

You don't add anything to the LinkedList in the method above!

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    With pointing out that AbstractTableModel has already implemented fireTableDataChanged for you, hence the reason why your been encourages NOT to override it – MadProgrammer Apr 23 '13 at 20:45
  • Thx, but when i call model.addElement(person); method and after that model.fireTableDataChanged() it doesn't work right. – veinhorn Apr 23 '13 at 21:03
  • @BorisMonson: the model itself should call the fire methods and they should do this within their add, remove methods, for example in my small code snippet above. Also: again, why the desire to add a "listener"? Also why use a LinkedList as your model's collection? – Hovercraft Full Of Eels Apr 23 '13 at 21:04
  • I thought that i have to implement one of the firexxx method. As for LinkedList, i wanted to try use another collection(no array like in all samples). I don't understand why when i use your implementation it doesn't work. – veinhorn Apr 23 '13 at 21:23
  • @BorisMonson: please see **Edit 2** in my answer above. – Hovercraft Full Of Eels Apr 23 '13 at 21:33
  • @Hovercraft Full Of Eels, thx, i understand that i should not implement this method, but i can't to understant in what position i must put it. – veinhorn Apr 23 '13 at 21:58
  • 1
    @BorisMonson: please see Edit 3. Also, consider simplifying your problem for us by creating and posting an [sscce](http://sscce.org). – Hovercraft Full Of Eels Apr 23 '13 at 22:01
  • @Hovercraft Full Of Eels, Big thanks, now all works excelent. – veinhorn Apr 23 '13 at 22:23
  • 1
    @HovercraftFullOfEels : Wow, to be true, I really was looking for such an explanation, to get some interest going in `JTable` thingy. The wordings used at the Java Docs always went over my head, but your words, wowo did some magic. Wish I could upvote this some more times :-) – nIcE cOw Apr 27 '13 at 15:11
  • @HovercraftFullOfEels : You're MOST WELCOME and KEEP SMILING :-) – nIcE cOw Apr 28 '13 at 02:49