構建一個JTable之前,應該設計好表格的列頭以及行數據,分別用final數組保存之:
final String [] names={"First Name","Last Name","Favorite Color",
"Favorite Number","Vegetarian"};
final Object [][] data={
{"Mark","Andrews","Red",new Integer(2),new Boolean(true)},
{"Tom","Chung","Green",new Integer(99),new Boolean(false)}
};
接下來,在創建JTable之前,需要構建一個實現了TableModel接口的AbstractTableModel類的實例,TableModel接口規定了JTable如何訪問表格中數據的模型。示例如下:
TableModel dataModel =new AbstractTableModel(){
public int getColumnCount(){return names.length;}//實現這個函數是必須的,因為抽象類AbstractTableModel中并沒有實現該函數
public int getRowCount(){return data.length;}//實現這個函數是必須的,因為抽象類AbstractTableModel中并沒有實現該函數
public Object getValueAt(int row,int col){return data[row][col];}//實現這個函數是必須的,因為抽象類AbstractTableModel中并沒有實現該函數
public String getColumnName(int column){return names[column];}//如果需要自己來命名列名稱,就必須override該方法
@SuppressWarnings("unchecked")
public Class getColumnClass(int col){return getValueAt(0,col).getClass();}//這個方法也因該重寫,因為AbstractTableModel中的實現僅僅是“return Object.class;”,因此我們需要override該方法
public boolean isCellEditable(int row,int col){return true;}//默認均返回false,因此如果希望表格的cell能夠被編輯,就需要override這個函數
public void setValueAt(Object aValue,int row,int col){//默認情況下,該函數的函數體是空的,因此如果希望表格的cell中的值能夠被更改,就必須override該函數
System.out.println("Setting value to: "+aValue);
data[row][col]=aValue;
}
};
接下來就可以創建JTable了:
JTable tableView=new JTable(dataModel);
至此,表格已經創建起來了。如果需要能夠對表格進行更進一步的操作,比如允許用戶編輯表格中各個單元格的內容,就需要看看下面的內容嘍:
我個人認為編輯表格是以列為單位的,
第一步,需要得到某一列:
TableColumn colorColumn=tableView.getColumn(names[2]);
第二步,需要給該列指定一個實現了TableCellEditor接口的編輯類,DefaultCellEditor類實現了該接口,因此直接構建DefaultCellEditor類的一個實例就ok了,需要說明的是,該類的實現方法只有三種,而且分別對應需要JCheckBox、JComboBox、JTextField三種類的實例:
colorColumn.setCellEditor(new DefaultCellEditor(comboBox));
第三步,給該列指定一個實現了TableCellRenderer接口的的渲染類(或稱作呈現/表現類),DefaultTableCellRenderer類實現了該接口,因此直接構建DefaultTableCellRenderer的一個實例就ok了:
DefaultTableCellRenderer colorColumnRenderer=new DefaultTableCellRenderer();
colorColumnRenderer.setBackground(Color.pink);
colorColumnRenderer.setHorizontalAlignment(JLabel.RIGHT);
colorColumnRenderer.setToolTipText("Click for combo box");
colorColumn.setCellRenderer(colorColumnRenderer);
需要說明的是,DefaultTableCellRenderer能夠設置的內容當然不局限于上述列出的這三個,還有很多,但是有一點很重要,就是如果你希望單元格的內容能夠按照某種方式來改變,比如用戶自己編輯了單元格內容后,我們如果希望單元格呈現的內容能夠根據用戶的輸入做更多的變化(而不僅僅是簡單的字符串替換,如果僅僅是字符串替換的話,那就不必廢這么多事了,DefaultTableCellRenderer類自帶的setValue實現方法就能夠完成任務了),而不在希望單元格的內容一成不變了,此時就不能簡單的創建一個DefaultTableCellRenderer類的實例了,而是需要創建一個DefaultTableCellRenderer類的派生類,而且需要override里面的setValue方法,通常我們都這樣做:
DefaultTableCellRenderer numberColumnRenderer=new DefaultTableCellRenderer(){
public void setValue(Object value){
int cellValue=(value instanceof Number) ? ((Number)value).intValue() : 0;
this.setForeground((cellValue > 30) ? Color.black : Color.red);
super.setValue(value);
}
};
在DefaultTableCellRenderer類中setValue方法的修飾符為protected,因此我們不能直接用DefaultTableCellRenderer的實例來使用該方法,而只能通過繼承DefaultTableCellRenderer類,然后在類的內部override該方法來實現定制特定的功能,從這里我們也能夠更深刻的理解為什么有些方法要定義成protected了,目的就是為了對外不可見,但是又能夠通過繼承的手段來實現用戶自己的定制,而且有些情況這是很必須的,比如在該處,我們可以試想一下,如果用public來修飾,則用戶可以直接通過產生實例來引用該方法,那么由于該類是作用于整個列的,而不僅僅是一個單元格,那么當你設定了setValue后,到底是該對列中所有的單元格都有效呢,還是該只對某一個單元格有效呢,這就很難說了。