如何在JTable中刷新数据我正在使用TableModel

嗨,

我创建了我的TableModel,并且在添加新行后想要刷新JTable。 应该向监听器添加什么来“刷新”JTable?

public class MyTableModel implements TableModel { private Set listeners = new HashSet(); //List staffs = Factory.getInstance().getStaffDAO().getAllStaff(); private List staffs; public MyTableModel(List 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) { } } 

这是我的添加行按钮的监听器:

  @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!!! } 

我试图在我的actionPerformed()中使用AbstractTableModel的方法firetabledatachanged(),但是在unluck中,它出现了ClassCastException。

更新1

WorkPlaceGui.java

 public class WorkPlaceGui extends JFrame implements ActionListener { AbstractTableModel model; JTable jTable; JScrollPane jScrollPane; public WorkPlaceGui()throws SQLException{ List 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 staffs; public MyTableModel(List 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 ""; } } 

你已经很难完成了。

首先,您直接从TableModel实现,其次,您未能实现监听器要求……

相反,尝试从AbstractTableModel扩展,它已经包含了侦听器注册和通知的实现。

您需要提供一种方法,允许您向表模型添加行。 在此方法中,您需要使用fireTableRowsInserted方法,该方法将使用模型通知任何表,已添加新行…

以示例更新

这是非常非常基本的例子。 它的唯一目的是演示fireTableRowsInserted的使用。 它使用Swing Timer每125毫秒添加一行,直到你杀掉它;)

 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 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); } } } 

更新了另一个例子

由于您的表模型由其自己的List支持,因此它与您的工厂没有任何关联。 它不知道何时添加或删除对象。 这意味着您有责任更新模型:

 public class MyTableModel extends AbstractTableModel { private List staffs; public MyTableModel(List 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 ""; } } 

并且你的行动改变了:

 @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(); } } 

您的类MyTableModel实现了TableModel ,但它没有将模型连接到视图的事件处理机制。 而是扩展AbstractTableModel ,如此处和此处所示。 AbstractTableModel提供了此所需的fireTable*方法。

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

好吧,首先,找到更多关于Observer模式的信息http://en.wikipedia.org/wiki/Observer_pattern )。

我建议你创建一个ObservableModel类,它将有一个PropertyChangeListeners列表。 您的StaffDAO应该扩展此ObservableModel 。 当添加新员工(即addStaff )时,您应该调用ObservableModel的firePorpertyChange或类似的东西。 firePropertyChange notify所有propertyChangeListeners。 其中一个监听器应该在你的表中注册,并且其propertyChanged方法应该通过刷新表(hd1)实现得到了很好的答案。

myTableModel.fireTableDataChanged(); 应该足以强制刷新你的桌子 。 像往常一样,如果您有其他问题,请随时发表评论。

对于更通用的解决方案,您可以使用行表模型并只实现getValueAt()和setValueAt()方法。

这里应该是一些代码,在添加新行后将触发我的表格!

该模型负责调用正确的fireXXX方法。

使用这种类型的铸造。

 ((AbstractTableModel)student.getModel()).fireTableCellUpdated();