How to update data in JTable I use TableModel

Hello,

I have created my Model table and want to update JTable after adding a new row. What needs to be added to the listener for the JTable "update"?

public class MyTableModel implements TableModel { private Set<TableModelListener> listeners = new HashSet<TableModelListener>(); //List<Staff> staffs = Factory.getInstance().getStaffDAO().getAllStaff(); private List<Staff> staffs; public MyTableModel(List<Staff> staffs){ this.staffs = staffs; } @Override public int getRowCount() { return staffs.size(); } @Override public int getColumnCount() { return 5; } @Override public String getColumnName(int columnIndex) { switch (columnIndex){ case 0: return "First Name"; case 1: return "Second Name"; case 2: return "Date"; case 3: return "Position"; case 4: return "Salary"; } return ""; } @Override public Class<?> getColumnClass(int columnIndex) { return Object.class; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } @Override public Object getValueAt(int rowIndex, int columnIndex) { Staff staff = staffs.get(rowIndex); switch (columnIndex){ case 0: return staff.getName(); case 1: return staff.getSurname(); case 2: return staff.getDate(); case 3: return staff.getPosition(); case 4: return staff.getSalary(); } return ""; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { } @Override public void addTableModelListener(TableModelListener l) { } @Override public void removeTableModelListener(TableModelListener l) { } } 

Here is my listener of my Add row button:

  @Override public void actionPerformed(ActionEvent e) { Staff staff = new Staff(); staff.setName(JOptionPane.showInputDialog("Enter First Name")); staff.setSurname(JOptionPane.showInputDialog("Enter Second Name")); staff.setDate(JOptionPane.showInputDialog("Enter Date")); staff.setPosition(JOptionPane.showInputDialog("Enter Position")); staff.setSalary(JOptionPane.showInputDialog("Enter Salary")); try { Factory.getInstance().getStaffDAO().addStaff(staff); } catch (SQLException e1) { e1.printStackTrace(); } !!!Here should be some code that will be firing my table after adding new row!!! } 

I tried to use the firetabledatachanged () AbstractTableModel method in my actionPerformed (), but with failure, this threw a ClassCastException.

UPDATE 1

WorkPlaceGui.java

 public class WorkPlaceGui extends JFrame implements ActionListener { AbstractTableModel model; JTable jTable; JScrollPane jScrollPane; public WorkPlaceGui()throws SQLException{ List<Staff> staffs = Factory.getInstance().getStaffDAO().getAllStaff(); for(int i = 0; i < 0; i++) { staffs.add(new Staff("First Name " + staffs.get(i).getName(), "Second Name " + staffs.get(i).getSurname(), "Date " + staffs.get(i).getDate(), "Position " + staffs.get(i).getPosition(), "Salary " + staffs.get(i).getSalary())); } model = new MyTableModel(staffs); jTable = new JTable(model); JButton jBtnAdd = new JButton(""); JButton jBtnDel = new JButton(""); JButton jBtnUpd = new JButton(""); JButton jBtnAdmin = new JButton(""); JPanel panelNorth = new JPanel(); JPanel panelCenter = new JPanel(); JPanel panelSouth = new JPanel(); jTable.setPreferredScrollableViewportSize(new Dimension(350, 150)); jScrollPane = new JScrollPane(jTable); panelNorth.setLayout(new FlowLayout()); panelNorth.add(jBtnAdd); panelNorth.add(jBtnDel); panelNorth.add(jBtnUpd); panelNorth.add(jBtnAdmin); panelCenter.add(jScrollPane); setLayout(new BorderLayout()); add(panelNorth, BorderLayout.NORTH); add(panelCenter, BorderLayout.CENTER); jBtnAdd.addActionListener(this); setPreferredSize(new Dimension(550, 300)); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setTitle("Staff data base"); pack(); setVisible(true); setLocationRelativeTo(null); } @Override public void actionPerformed(ActionEvent e) { Staff staff = new Staff(); staff.setName(JOptionPane.showInputDialog("Enter First Name")); staff.setSurname(JOptionPane.showInputDialog("Enter Second Name")); staff.setDate(JOptionPane.showInputDialog("Enter Date")); staff.setPosition(JOptionPane.showInputDialog("Enter Position")); staff.setSalary(JOptionPane.showInputDialog("Enter Salary")); try { Factory.getInstance().getStaffDAO().addStaff(staff); } catch (SQLException e1) { e1.printStackTrace(); } model.fireTableDataChanged(); } } 

MyTableModel.java

 public class MyTableModel extends AbstractTableModel { private List<Staff> staffs; public MyTableModel(List<Staff> staffs){ this.staffs = staffs; } @Override public int getRowCount() { return staffs.size(); } @Override public int getColumnCount() { return 5; } @Override public Object getValueAt(int rowIndex, int columnIndex) { Staff staff = staffs.get(rowIndex); switch (columnIndex){ case 0: return staff.getName(); case 1: return staff.getSurname(); case 2: return staff.getDate(); case 3: return staff.getPosition(); case 4: return staff.getSalary(); } return ""; } } 

+4
source share
6 answers

You did it with difficulty.

First of all, you implemented directly from TableModel , and secondly, you were not able to fulfill the listener's requirements ...

Instead, try switching from AbstractTableModel , which already includes implementations of registering and notifying the listener.

You will need to provide a method that allows you to add a row to the table model. In this method, you need to use the fireTableRowsInserted method, which will notify any tables using the model that a new row has been added ...

Refresh with example

This is a VERY, VERY simple example. The only intention is to demonstrate the use of fireTableRowsInserted . It uses Swing Timer to add a new line every 125 milliseconds until you kill it;)

 import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.table.AbstractTableModel; public class DynamicTable { public static void main(String[] args) { new DynamicTable(); } public DynamicTable() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } final MyTableModel model = new MyTableModel(); JTable table = new JTable(model); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new JScrollPane(table)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); Timer timer = new Timer(125, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { model.addRow(); } }); timer.start(); } }); } public class MyTableModel extends AbstractTableModel { private List<String[]> rows; public MyTableModel() { rows = new ArrayList<>(25); } @Override public int getRowCount() { return rows.size(); } @Override public int getColumnCount() { return 4; } @Override public Class<?> getColumnClass(int columnIndex) { return String.class; } @Override public Object getValueAt(int rowIndex, int columnIndex) { String[] row = rows.get(rowIndex); return row[columnIndex]; } public void addRow() { int rowCount = getRowCount(); String[] row = new String[getColumnCount()]; for (int index = 0; index < getColumnCount(); index++) { row[index] = rowCount + "x" + index; } rows.add(row); fireTableRowsInserted(rowCount, rowCount); } } } 

Updated with another example.

Since your table model is supported by its own List , it has no connection to your factory. He does not know when you add or remove objects from it. This means that you are responsible for updating the model:

 public class MyTableModel extends AbstractTableModel { private List<Staff> staffs; public MyTableModel(List<Staff> staffs){ this.staffs = staffs; } @Override public int getRowCount() { return staffs.size(); } @Override public int getColumnCount() { return 5; } public void add(Staff staff) { int size = getSize(); staffs.add(staff); fireTableRowsInserted(size, size); } public void remove(Staff staff) { if (staffs.contains(staff) { int index = stafff.indexOf(staff); staffs.remove(staff); fireTableRowsDeleted(index, index); } } @Override public Object getValueAt(int rowIndex, int columnIndex) { Staff staff = staffs.get(rowIndex); switch (columnIndex){ case 0: return staff.getName(); case 1: return staff.getSurname(); case 2: return staff.getDate(); case 3: return staff.getPosition(); case 4: return staff.getSalary(); } return ""; } } 

And your actionPerformed :

 @Override public void actionPerformed(ActionEvent e) { Staff staff = new Staff(); staff.setName(JOptionPane.showInputDialog("Enter First Name")); staff.setSurname(JOptionPane.showInputDialog("Enter Second Name")); staff.setDate(JOptionPane.showInputDialog("Enter Date")); staff.setPosition(JOptionPane.showInputDialog("Enter Position")); staff.setSalary(JOptionPane.showInputDialog("Enter Salary")); try { Factory.getInstance().getStaffDAO().addStaff(staff); ((MyTableModel)model).add(staff); } catch (SQLException e1) { e1.printStackTrace(); } } 
+12
source

Your MyTableModel class implements TableModel , but it does not have an event processing mechanism to connect the model to the view. Instead, continue with AbstractTableModel , as shown here and here . AbstractTableModel provides the fireTable* methods needed to do this.

 public void setValueAt(Object value, int row, int col) { data[row][col] = value; fireTableCellUpdated(row, col); } 
+8
source

Well, first of all, find a more observer pattern ( http://en.wikipedia.org/wiki/Observer_pattern ).

I suggest creating an ObservableModel class that will have a list of PropertyChangeListeners. Your StaffDAO should extend this ObservableModel . When new staff is added (i.e. addStaff is called), you should call ObservableModel firePorpertyChange or something like that. firePropertyChange notify all properties notify . One of these listeners must be registered in your table, and its propertyChanged method must be implemented with the table update (hd1). Good answer.

+3
source

myTableModel.fireTableDataChanged(); should be enough to force update the table . As usual, if you have additional problems, feel free to leave a comment.

+2
source

For a more general solution, you can use the String Table Model and simply implement the getValueAt () and setValueAt () methods.

There should be some code that will run my table after adding a new row!

The model is responsible for invoking the proper fireXXX method.

+2
source

Use this type of casting.

 ((AbstractTableModel)student.getModel()).fireTableCellUpdated(); 
+1
source

Source: https://habr.com/ru/post/1483092/


All Articles