日期:2014-05-20  浏览次数:20805 次

[swing] 写一个DefaultTableModel子类。跑不动,谁帮看看
跟了一下程序。没跑Model的构造函数就直接调用Model的getRowCount()方法。。。

import java.awt.BorderLayout;

import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class DemoTable extends JFrame {
private JButton btn;
private JTable tbl;
private Model m;
public DemoTable (){
initComponents();
}
private void initComponents(){
m = new Model();
tbl = new JTable(m);
JPanel pan = new JPanel();
this.setContentPane(pan);
pan.setLayout(new BorderLayout());
JScrollPane jsp = new JScrollPane();
jsp.setViewportView(tbl);
pan.add(jsp, BorderLayout.CENTER);
}
private static void createAndShowGui() {
DemoTable dt = new DemoTable();
dt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dt.setMinimumSize(new Dimension(500, 400));
dt.setLocationRelativeTo(null);
dt.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGui();
}
});
}
static class Model extends DefaultTableModel {
private ArrayList<String> data = new ArrayList(); 
public Model(){
data = new ArrayList();
}
public boolean isCellEditable(){
return false;
}
public void addRow(String rowData) {
data.add(rowData);
}
public void removeRow(String rowData) {
data.remove(rowData);
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 1;
}
public Object getVaultAt(int row, int col) {
return data.get(row);
}
}
}

------最佳解决方案--------------------

这是典型的设计问题

DefaultTableModel 在constructor里调用了可以被override的方法getRowCount()。

建议 extends AbstractTableModel

DefaultTableModel 还用了 Vector,而且是用了丕型的 Vector,足以说明这个类既古老又设计的时候欠考虑。
如果非要继承它,可以用 lazy instantiation:


    @Override
    public int getRowCount() {
      
      return getData().size();
    }

    private List<String> getData() {
      
      if( data == null )
        data = new ArrayList<String>();
      return data;
    }



为什么说 DefaultTableModel 用了 Vector 欠考虑,因为

1 - 所有针对 TableModel 的查询都应该是在EDT中,即单线程环境。
2 - 如果要在别的线程中对 TabelModel 里的数据做更改,可以用更高效的方式,更灵活的设计,最好能保证查询操作的无锁,用Vector就是简单粗暴,——Vector本身就是很糟糕的设计。