您好,
我已经创建了我的TableModel,并且在添加新行后想要刷新JTable。应该向听众添加什么来刷新"的JTable?
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) {
}
}
这是我的添加行按钮的监听器:
@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<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 "";
}
}
答案 0 :(得分:12)
你已经很难完成了。
首先,你直接从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<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);
}
}
}
由于您的表模型由其自己的List
支持,因此它与您的工厂没有任何关联。它不知道何时添加或删除对象。这意味着您有责任更新模型:
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 "";
}
}
您的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();
}
}
答案 1 :(得分:8)
您的类MyTableModel
实现了TableModel
,但它没有将模型连接到视图的事件处理机制。而是展开AbstractTableModel
,如here和here所示。 AbstractTableModel
提供了此所需的fireTable*
方法。
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
答案 2 :(得分:3)
首先,请详细了解观察者模式(http://en.wikipedia.org/wiki/Observer_pattern)。
我建议你创建一个 ObservableModel 类,它将包含一个PropertyChangeListeners列表。您的 StaffDAO 应扩展此 ObservableModel 。添加新员工(即调用addStaff
)后,您应该调用ObservableModel的firePorpertyChange
或类似的东西。 firePropertyChange
notify
所有propertyChangeListeners。其中一个监听器应该在你的表中注册,并且应该通过刷新表(hd1)来实现其propertyChanged
方法有一个很好的答案。
答案 3 :(得分:2)
myTableModel.fireTableDataChanged();
应该足够force a refresh of your table。像往常一样,如果您有其他问题,请随时发表评论。
答案 4 :(得分:2)
对于更通用的解决方案,您可以使用Row Table Model并只实现getValueAt()和setValueAt()方法。
这应该是一些代码,在添加新行后将触发我的表格!
该模型负责调用正确的fireXXX方法。
答案 5 :(得分:1)
使用此类型的施法。
((AbstractTableModel)student.getModel()).fireTableCellUpdated();