JTable使用方法

Jtable是Swing中經常使用的一個控件,對它的使用方法瞭解的不夠全面,看了這個帖子後,大體有所清楚:

Swing之JTable的詳細介紹 
8-1:使用JTable組件:
類層次結構圖:
java.lang.Object
--java.awt.Component
--java.awt.Container
--javax.swing.JComponent
--javax.swing.JTabel
在使用JTable以前,我們先看一下它的構造函數有哪些, 以及應該如何使用:

JTabel構造函數:
JTable():建立一個新的JTables,並使用系統默認的Model.
JTable(int numRows,int numColumns):建立一個具有numRows行,numColumns列的空表格,使用的是DefaultTableModel.
JTable(Object[][] rowData,Object[][] columnNames):建立一個顯示二維數組數據的表格,且可以顯示列的名稱。
JTable(TableModel dm):建立一個JTable,有默認的字段模式以及選擇模式,並設置數據模式。
JTable(TableModel dm,TableColumnModel cm):建立一個JTable,設置數據模式與字段模式,並有默認的選擇模式。
JTable(TableModel dm,TableColumnModel cm,ListSelectionModel sm):建立一個JTable,設置數據模式、字段模式、與選擇模式。
JTable(Vector rowData,Vector columnNames):建立一個以Vector爲輸入來源的數據表格,可顯示行的名稱。

我們先以Array構造方式,說明如何利用JTable來建立一個簡單的表格:


1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4 import java.util.*;
5 public class SimpleTable{
6 public SimpleTable(){
7 JFrame f=new JFrame();
8 Object[][] playerInfo={
9   {"阿呆",new Integer(66),new Integer(32),new Integer(98),new Boolean(false)},
10 {"阿呆",new Integer(82),new Integer(69),new Integer(128),new Boolean(true)},
11 }; 
12 String[] Names=;
13 JTable table=new JTable(playerInfo,Names);
14 table.setPreferredScrollableViewportSize(new Dimension(550,30));
15 JScrollPane scrollPane=new JScrollPane(table);
16 f.getContentPane().add(scrollPane,BorderLayout.CENTER);
17 f.setTitle("Simple Table");
18 f.pack();
19 f.show();
20 f.addWindowListener(new WindowAdapter() {
21 public void windowClosing(WindowEvent e) {
22 System.exit(0);
23 }
24 });
24 } 
25 public static void main(String[] args){
26   SimpleTable b=new SimpleTable();
27 }
28 } 


表格由兩部份組成:分別是行標題(Column Header)與行對象(Column Object).利用JTable所提供的getTableHeader()方法取得
行標題。在這個例子中,我們將JTable放在JScrollPane中,這種做法可以將Column Header與Colmn Object完整的顯示出來,因爲
JScrollPane會自動取得Column Header.但如果文壇讀者將上面第15行去掉並修改第16行:
f.getContentPane().add(table,BorderLayout.CENTER); 
則運行結果你會發現Column Header不見了。

如果你不想用JScrollPane,要解決這個問題,你必須將程序修改如下:


JTable table=new JTable(p,n);
table.setPreferredScrollableViewportSize(new Dimension(550,30));
f.getContentPane().add(table.getTableHeader(),BorderLayout.NORTH);
f.getContentPane().add(table,BorderLayout.CENTER);


運行結果就會跟之前一樣有行標題了.
上面的運行結果就會跟發現,每個字段的寬度都是一樣的,除非你自行拉曳某個列寬。若我們想一開始就設置列寬的值,可以利
用TableColumn類所提供的setPreferredWidth()方法來設置,並可利用JTable類所提供的setAutoResizeMode()方法來設置調整某個
列寬時其他列寬的變化情況,我們看下面這個例子:



import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class SimpleTable2{
public SimpleTable2(){
JFrame f=new JFrame();
Object[][] p={
{"阿呆",new Integer(66),new Integer(32),new Integer(98),new Boolean(false),new Boolean(false)},
{"阿呆",new Integer(82),new Integer(69),new Integer(128),new Boolean(true),new Boolean(false)},
}; 
String[] n=;
TableColumn column=null;
JTable table=new JTable(p,n);
table.setPreferredScrollableViewportSize(new Dimension(550,30));
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
for (int i=0;i<6;i++){
//利用JTable中的getColumnModel()方法取得TableColumnModel對象;再利用TableColumnModel界面所定義的getColumn()方法取
//TableColumn對象,利用此對象的setPreferredWidth()方法就可以控制字段的寬度.
column=table.getColumnModel().getColumn(i);
if ((i%2)==0)
column.setPreferredWidth(150);
else
column.setPreferredWidth(50);
}
JScrollPane scrollPane=new JScrollPane(table);
f.getContentPane().add(scrollPane,BorderLayout.CENTER);
f.setTitle("Simple Table");
f.pack();
f.show();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});   
}
public static void main(String[] args){
new SimpleTable2();
}
}


列可調整的5個參數:
AUTO_RESIZE_SUBSEQUENT_COLUMENS:當調整某一列寬時,此字段之後的所有字段列寬都會跟着一起變動。此爲系統默認值。
AUTO_RESIZE_ALL_COLUMNS:當調整某一列寬時,此表格上所有字段的列寬都會跟着一起變動。
AUTO_RESIZE_OFF:當調整某一列寬時,此表格上所有字段列寬都不會跟着改變。
AUTO_RESIZE_NEXT_COLUMN:當調整某一列寬時,此字段的下一個字段的列寬會跟着改變,其餘均不會變。
AUTO_RESIZE_LAST_COLUMN:當調整某一列寬時,最後一個字段的列寬會跟着改變,其餘均不會改變。

由以上範例可知,利用Swing來構造一個表格其實很簡單的,只要你利用Vector或Array來作爲我們表格的數據輸入,將Vector或Array的
內容填入JTable中,一個基本的表格就產生了。不過,雖然利用JTable(Object[][] rowData,Object[][] columnNames)以及
JTable(Vector rowData,Vector columnNames)構造函數來構造構造JTable很方便,但卻有些缺點。例如上例中,我們表格中的每個字段
(cell)一開始都是默認爲可修改的,用戶因此可能修改到我們的數據;其次,表格中每個單元(cell)中的數據類型將會被視爲同一種。在我
們的例子中,數據類型皆被顯示爲String的類型,因此,原來的數據類型聲明爲Boolean的數據會以String的形式出現而不是以檢查框(
Check Box)出現。
除此之外,如果我們所要顯示的數據是不固定的,或是隨情況而變,例如同樣是一份成績單,老師與學生所看到的表格就不會一樣,顯
示的外觀或操作模式也許也不相同。爲了因應這些種種複雜情況,上面簡單的構造方式已不宜使用,Swing提供各種Model(如:
TableModel、TableColumnModel與ListSelectionModel)來解決上述的不便,以增加我們設計表格的彈性。我們下面就先對TableModel來
做介紹:

8-2:TableModel
TableModel類本身是一個interface,在這個interface裏面定義了若干的方法:包括了存取表格字段(cell)的內容、計算表格的列數等等
的基本存取操作,讓設計者可以簡單地利用TableModel來實作他所想要的表格。TableModel界面是放在javax.swing.table package中,這
個package定義了許多JTable會用到的各種Model,讀者可利用java api文件找到這個package,並由此package找到各類或界面所定義的方法

TableModel方法:
void addTableModelListener(TableModelListener l):使表格具有處理TableModelEvent的能力。當表格的Table Model有所
變化時,會發出TableModel Event事件信息.
Class getColumnClass(int columnIndex):返回字段數據類型的類名稱.
int getColumnCount():返回字段(行)數量.
String getColumnName(int columnIndex):返回字段名稱.
int getRowCount():返回數據列數量.
Object getValueAt(int rowIndex,int columnIndex):返回數據某個cell中的值.
boolean isCellEditable(int rowIndex,int columnIndex):返回cell是否可編輯,true的話爲可編輯.
void removeTableModelListener(TableModelListener l):從TableModelListener中移除一個listener.
void setValueAt(Object aValue,int rowIndex,int columnIndex):設置某個cell(rowIndex,columnIndex)的值;

由於TableModel本身是一個Interface,因此若要直接實現此界面來建立表格並不是件輕鬆的事.幸好java提供了兩個類分別實現了這個
界面,一個是AbstractTableModel抽象類,一個是DefaultTableModel實體類.前者實現了大部份的TableModel方法,讓用戶可以很有彈性地構
造自己的表格模式;後者繼承前者類,是java默認的表格模式.這三者的關係如下所示:
TableModel---implements--->AbstractTableModel-----extends--->DefaultTableModel

8-3:AbstractTableModel:

java提供的AbstractTableModel是一個抽象類,這個類幫我們實現大部份的TableModel方法,除了getRowCount(),getColumnCount(),
getValueAt()這三個方法外.因此我們的主要任務就是去實現這三個方法.利用這個抽象類就可以設計出不同格式的表格.我們來看看它所
提供的方法:
AbstractTableModel方法:
void addTableModelListener(TableModelListener l):使表格具有處理TableModelEvent的能力.當表格的Table Model有所變化時,會發
出TableModelEvent事件信息.
int findColumn(String columnName):尋找在行名稱中是否含有columnName這個項目.若有,則返回其所在行的位置;反之則返回-1表示
未找到.
void fireTableCellUpdated(int row, int column):通知所有的Listener在這個表格中的(row,column)字段的內容已經改變了.
void fireTableChanged(TableModelEvent e):將所收的事件通知傳送給所有在這個table model中註冊過的TableModelListeners.
void fireTableDataChanged():通知所有的listener在這個表格中列的內容已經改變了.列的數目可能已經改變了,因此JTable可能需要
重新顯示此表格的結構.
void fireTableRowsDeleted(int firstRow, int lastRow):通知所有的listener在這個表格中第firstrow行至lastrow列已經被刪除了.
void fireTableRowsUpdated(int firstRow, int lastRow)
:通知所有的listener在這個表格中第firstrow行至lastrow列已經被修改了.
void fireTableRowsInserted(int firstRow, int lastRow):通知所有的listener在這個表格中第firstrow行至lastrow列已經被加入了
.

void fireTableStructureChanged():通知所有的listener在這個表格的結構已經改變了.行的數目,名稱以及數據類型都可能已經改變了
.
Class getColumnClass(int columnIndex):返回字段數據類型的類名稱.
String getColumnName(int column):若沒有設置列標題則返回默認值,依次爲A,B,C,...Z,AA,AB,..;若無此column,則返回一個空的String
.
Public EventListener[] getListeners(Class listenerType):返回所有在這個table model所建立的listener中符合listenerType的
listener,並以數組形式返回.
boolean isCellEditable(int rowIndex, int columnIndex)
:返回所有在這個table model所建立的listener中符合listenerType形式的
listener,並以數組形式返回.
void removeTableModelListener(TableModelListener l):從TableModelListener中移除一個listener.

void setValueAt(Object aValue, int rowIndex, int columnIndex)
:設置某個cell(rowIndex,columnIndex)的值.
若你仔細比較TableModel所定義的方法與上述AbstractTableModel所提供的方法,你可以發現,AbstractTableModel抽象類並沒有實現
getRowCount(),getColumnCount(),getValueAt()這三個方法,這也就是爲什麼我們要去實現這三個方法的原因.下面我們來看如何使用
AbstractTableModel來實作出自己想要的表格模式.

範例:TableModel1.java



import javax.swing.table.AbstractTableModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TableModel1{
public TableModel1() {
JFrame f = new JFrame();
MyTable mt=new MyTable();
JTable t=new JTable(mt);
t.setPreferredScrollableViewportSize(new Dimension(550, 30));
JScrollPane s = new JScrollPane(t);
f.getContentPane().add(s, BorderLayout.CENTER);
f.setTitle("JTable1");
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});
}
public static void main(String args[]) {

new TableModel1();
}
}
class MyTable extends AbstractTableModel{
Object[][] p = {
{"阿呆", new Integer(66), 
new Integer(32), new Integer(98), new Boolean(false),new Boolean(false)},
{"阿瓜", new Integer(85), 
new Integer(69), new Integer(154), new Boolean(true),new Boolean(false)}, 
};
String[] n = {"姓名", 
"語文",
"數學",
"總分",
"及格",
"作弊"};
public int getColumnCount() {
return n.length;
}
public int getRowCount() {
return p.length;
}
public String getColumnName(int col) {
return n[col];
}
public Object getValueAt(int row, int col) {
return p[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
}


上例中表格內的數據類型不論是String,int或是Boolean類型,都均以string的類型顯示.例如在及格的字段中,原本的數據是以Boolean
類型來表示,但顯示在JTable上時便轉換成字符串形式,若想要使表格能顯示出不同的數據類型,我們要在MyTable中Override寫getColumnCl
ass()方法,這個方法可以讓我們分辨出表格中每一行的數據類型,並將此類型作適當的顯示:


public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}


這樣"作弊"會以Check Box顯示,數據類型一律靠右顯示,String類型一律靠左顯示.
TableModel2.java


import javax.swing.table.AbstractTableModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TableModel2 implements ActionListener{

JTable t = null;

public TableModel2() {

JFrame f = new JFrame("DataModel");
JButton b1 = new JButton("數學老師");
b1.addActionListener(this);
JButton b2 = new JButton("學生阿呆");
b2.addActionListener(this);
JPanel panel = new JPanel();
panel.add(b1);
panel.add(b2);

t=new JTable(new MyTable(1));
t.setPreferredScrollableViewportSize(new Dimension(550, 30));
JScrollPane s = new JScrollPane(t);

f.getContentPane().add(panel, BorderLayout.NORTH);
f.getContentPane().add(s, BorderLayout.CENTER);
f.pack();
f.setVisible(true);

f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});
}

public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("學生阿呆"))
t.setModel(new MyTable(1));
if (e.getActionCommand().equals("數學老師"))
t.setModel(new MyTable(2));
t.revalidate();
}

public static void main(String args[]) {

new TableModel2();
}
}

class MyTable extends AbstractTableModel{

Object[][] p1 = {
{"阿呆", "1234",new Integer(66), 
new Integer(50), new Integer(116), new Boolean(false),new Boolean(false)}};

String[] n1 = ;

Object[][] p2 = {
{"阿呆", "1234",new Integer(50), new Boolean(false),new Boolean(false),"01234"},
{"阿瓜", "1235",new Integer(75), new Boolean(true),new Boolean(false),"05678"}};

String[] n2 = ;

int model = 1;

public MyTable(int i){
model = i;
}

public int getColumnCount() {
if(model ==1)
return n1.length;
else
return n2.length;
}

public int getRowCount() {
if(model ==1)
return p1.length;
else
return p2.length;
}

public String getColumnName(int col) {
if(model ==1)
return n1[col];
else
return n2[col];
}

public Object getValueAt(int row, int col) {
if(model == 1)
return p1[row][col];
else
return p2[row][col];
}

public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
}


8-4:TableColumnModel:
TableColumnModel本身是一個Interface,裏面定義了許多與表格的"列(行)"有關的方法,例如增加列,刪除列,設置與取得"列"的相關信
息.通常我們不會直接實現TableColumnModel界面,而是會利用JTable的getColumnModel()方法取得TableColumnModel對象,再利用此對象對
字段做設置.舉例來說,如果我們想設計的表格是包括有下拉式列表的Combo Box,我們就能利用TableColumnModel來達到這樣的效果.
我們先看看下面的例子:


import javax.swing.table.AbstractTableModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ColumnModelTest{

public ColumnModelTest() {

JFrame f = new JFrame();
/*由於我們的MyTable類繼承了AbstractTableModel並且實作了getColmunCount(),getRowCount(),getValueAt()方法.因此我們可以通
*過MyTable來產生TableModel的實體.
*/ 
MyTable mt=new MyTable();
JTable t=new JTable(mt);//我們利用MyTable來建立JTable.
JComboBox c = new JComboBox();//建立一個JComboBox的對象.
c.addItem("Taipei");//我們在新建立的JComboBox對象裏新增三個項目.
c.addItem("ChiaYi");
c.addItem("HsinChu");
/*我們利用JTable所提供的getTableColumnModel()方法取得TableColumnModel對象,再由TableColumnModel類所提供的getColumn()方
*法取得TableColumn對象,TableColumn類可針對表格中的每一行做具體的設置,例如設置字段的寬度,某行的標頭,設置輸入較複雜的
*數據類型等等.在這裏,我們利用TableColumn類所提供的setCellEditor()方法,將JComboBox作爲第二行的默認編輯組件.
*/
t.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(c));
t.setPreferredScrollableViewportSize(new Dimension(550, 30));
JScrollPane s = new JScrollPane(t);

f.getContentPane().add(s, BorderLayout.CENTER);
f.setTitle("ColumnModelTest");
f.pack();
f.setVisible(true);

f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});
}

public static void main(String args[]) {

new ColumnModelTest();
}

}

class MyTable extends AbstractTableModel{

Object[][] p = {
{"阿呆", "Taipei",new Integer(66), 
new Integer(32), new Integer(98), new Boolean(false),new Boolean(false)},
{"阿瓜", "ChiaYi",new Integer(85), 
new Integer(69), new Integer(154), new Boolean(true),new Boolean(false)}, 
};

String[] n = {"姓名", 
"居住地",
"語文",
"數學",
"總分",
"及格",     
"作弊"};

public int getColumnCount() {
return n.length;
}

public int getRowCount() {
return p.length;
}

public String getColumnName(int col) {
return n[col];
}

public Object getValueAt(int row, int col) {
return p[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*public boolean isCellEditable(int rowIndex, int columnIndex) {
return true; 
}
public void setValueAt(Object value, int row, int col) {
p[row][col] = value;
fireTableCellUpdated(row, col);
}*/
}


讀者運行此程序可以發現,利用繼承AbstractTableModel抽象類所產生的JTable的內容是不能被修改的.那如果想要讓用戶可以修改表格
中的某一個字段,例如勾選Check Box或是直接修改某個字段的數字,該怎麼做呢?很簡單,只要我們在範例中的MyTable類中覆寫AbstractTab
leModel抽象類中的isCellEditable()方法即可.下面即是isCellEditable()的實作:
public boolean isCellEditable(int rowIndex,int columnIndex){
return true;
}
在isCellEditable()中,我們只有一行簡單的程序代碼:return true,意思是將我們表格內的每個cell都變成可修改.但僅僅修改這個程
序代碼還不行,你可以發現雖然表格現在變成了可以修改了,但更改完之後按下[Enter]鍵,內容馬上恢復成原有的值!解決的方法是覆寫
AbstractTableModel抽象類中的setValueAt()方法,這個方法主要是讓我們將改過的值存入表格中,如下所示:



public void setValueAt(Object value,int row,int col)


其中value爲我們所更改的值,我們將value存入p[row][col]中,並且調用firTableCellUpdated()函數來告訴我們的系統表格已經做了更
改了,關於這一部份,我們後面會再對事件處理作詳細地介紹,在此範例中有沒有加入fireTableCellUpdated()方法對運行結果不會造成影響
.

8-5:SelectionModel
表格的選擇模式是依據我們前面所講的ListSelectionModel而來,因此它的操作模式與事件處理跟JList沒什麼分別!我們稍微複習一
下ListSelectionModel這個Interface,它包含了3個常數值,如下:
static int SINGLE_SELECTION
static int SINGLE_INTERVAL_SELECTION
static int MULTIPLE_INTERVAL_SELECTION
分別可讓用戶作單一選擇,連續區間選擇與多重選擇.當用戶作後面兩個模式的操作時,應配合[Shift]鍵或[Ctrl]鍵.
要使用ListSelectionModel可利用JTable的getSelectionModel()方法取得ListSelectionModel對象,再利用ListSelectionModel界面所
定義的setSelectionModel()來設置選擇模式.
如同JList一般,當用戶對錶格作數據域位的選取時會產生ListSelectionEvent事件,要處理這個事件就必須實現ListSelectionListener
這個界面,此界面定義了一個方法,那就是valueChanged().
我們來看下面的例子,用戶可在按鈕上選擇哪種選擇模式,當用戶選取表格數據時,程序會將用戶選取的數據顯示在表格下面的JLabel中.

SelectionModelDemo.java


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class SelectionModelDemo implements ActionListener,ListSelectionListener{
JTable table=null;
ListSelectionModel selectionMode=null;
JLabel label=null;//顯示用戶選取表格之用
public SelectionModelDemo(){
JFrame f=new JFrame();
String[] name=;
String[][] data=new String[5][5];
int value=1;
for(int i=0;i<data.length;i++){
    for (int j=0;j<data.length;j++)
}
table=new JTable(data,name);
table.setPreferredScrollableViewportSize(new Dimension(400,80));
table.setCellSelectionEnabled(true);//使得表格的選取是以cell爲單位,而不是以列爲單位.若你沒有寫此行,則在選取表格數
//據時以整列爲單位.
selectionMode=table.getSelectionModel();//取得table的ListSelectionModel.
selectionMode.addListSelectionListener(this);
JScrollPane s=new JScrollPane(table);
JPanel panel=new JPanel();
JButton b=new JButton("單一選擇");
panel.add(b);
b.addActionListener(this);
b=new JButton("連續區間選擇");
panel.add(b);
b.addActionListener(this);
b=new JButton("多重選擇");   
panel.add(b);
b.addActionListener(this);

label=new JLabel("你選取:");

Container contentPane=f.getContentPane();
contentPane.add(panel,BorderLayout.NORTH);
contentPane.add(s,BorderLayout.CENTER);
contentPane.add(label,BorderLayout.SOUTH);

f.setTitle("SelectionModelDemo");
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});   
}
/*處理按鈕事件,利用ListSelectionModel界面所定義的setSelectionMode()方法來設置表格選取模式.*/
public void actionPerformed(ActionEvent e){
if (e.getActionCommand().equals("單一選擇"))
selectionMode.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
if (e.getActionCommand().equals("連續區間選擇"))
selectionMode.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
if (e.getActionCommand().equals("多重選擇"))
selectionMode.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.revalidate();


/*當用戶選取表格數據時會觸發ListSelectionEvent,我們實現ListSelectionListener界面來處理這一事件.ListSelectionListener界
*面只定義一個方法,那就是valueChanged().
*/   
public void valueChanged(ListSelectionEvent el){
String tempString="";
//JTable的getSelectedRows()與getSelectedColumns()方法會返回已選取表格cell的index Array數據.
int[] rows=table.getSelectedRows();
int[] columns=table.getSelectedColumns();

//JTable的getValueAt()方法會返回某行的cell數據,返回值是Object數據類型,因此我們要自行轉成String數據類型.
for (int i=0;i<rows.length;i++){
for (int j=0;j<columns.length;j++)
tempString = tempString+" "+(String)table.getValueAt(rows, columns[j]); 
}
label.setText("你選取:"+tempString);
}
public static void main(String[] args){
new SelectionModelDemo();
}
}
說明:
在此範例中,我們要處理ActionEvent與ListSelectionEvent,因此在程序中我們要實現ActionListenrer與ListSelectionListener界
面,而ListSelectionEvent是屬於Swing事件,因此程序中我們要import javax.swing.event package進來.


8-6:DefaultTableModel
我們曾提到過DefaultTableModel類,並說明了此類是繼承AbstractTableModel抽象類而來,且實現了getColumnCount(),getRowCount()
與getValueAt()3個方法.因此在實際的使用上,DefaultTableModel比AbstractTableModel要來得簡單許多,也較常被拿來使用
.DefaultTableModel內部使用Vector來使用表格的數據,若佻所要顯示的表格格式是比較單純的變化,筆者建議使用DefaultTableModel類會
來得方便也簡單許多.若佻所要顯示的數據模式非常複雜,例如我們所舉的成績表格外加學生選課信息等,像這類的表格通常顯示的信息會因
人面異,因此使用AbstractTableModel會比較容易設計些.

下面是DefaultTableModel的構造函數:
DefaultTableModel():建立一個DefaultTableModel,裏面沒有任何數據.
DefaultTableModel(int numRows,int numColumns):建立一個指定行列數的DefaultTableModel.
DefaultTableModel(Object[][] data,Object[] columnNames):建立一個DefaultTableModel,輸入數據格式爲Object Array.系統會
自動調用setDataVector()方法來設置數據。
DefaultTableModel(Object[] columnNames,int numRows):建立一個DefaultTableModel,並具有Column Header名稱與行數信息。
DefaultTableModel(Vector columnNames,int numRows):建立一個DefaultTableModel,並具有column Header名稱與行數信息。
DefaultTableModel(Vector data,Vector columnNames):建立一個DefaultTableModel,輸入數據格式爲Vector.系統會自動調用
setDataVector()方法來設置數據。

DefaultTableModel類提供相當多好用的方法,如之前我們談論過的getColumnCount(),getRowCount(),getValueAt(),isCellEditable()
setValueAt()等方法,均可直接使用。且DefaultTableModel也提供了addColumn()與addRow()等方法,可讓我們隨時增加表格的數據。下
面我們就舉一個動態增加表格字段的例子:



import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class AddRemoveCells implements ActionListener
{
JTable table = null;
DefaultTableModel defaultModel = null;

public AddRemoveCells()
{
JFrame f = new JFrame();
String[] name = {"字段 1","字段 2","字段 3","字段 4","字段 5"};
String[][] data = new String[5][5];
int value =1;
for(int i=0; i<data.length; i++)
{
for(int j=0; j<data.length ; j++)
data[j] = String.valueOf(value++);
}

defaultModel = new DefaultTableModel(data,name);
table=new JTable(defaultModel);
table.setPreferredScrollableViewportSize(new Dimension(400, 80));
JScrollPane s = new JScrollPane(table);

JPanel panel = new JPanel();
JButton b = new JButton("增加行");
panel.add(b);
b.addActionListener(this);
b = new JButton("增加列");
panel.add(b);
b.addActionListener(this);
b = new JButton("刪除行");
panel.add(b);
b.addActionListener(this);
b = new JButton("刪除列");
panel.add(b);
b.addActionListener(this);

Container contentPane = f.getContentPane();
contentPane.add(panel, BorderLayout.NORTH);
contentPane.add(s, BorderLayout.CENTER);

f.setTitle("AddRemoveCells");
f.pack();
f.setVisible(true);

f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) 
});
}
/*要刪除列必須使用TableColumnModel界面定義的removeColumn()方法。因此我閃先由JTable類的getColumnModel()方法取得
*TableColumnModel對象,再由TableColumnModel的getColumn()方法取得要刪除列的TableColumn.此TableColumn對象當作是
*removeColumn()的參數。刪除此列完畢後必須重新設置列數,也就是使用DefaultTableModel的setColumnCount()方法來設置。
*/
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("增加列"))
defaultModel.addColumn("增加列");
if(e.getActionCommand().equals("增加行"))
defaultModel.addRow(new Vector());
if(e.getActionCommand().equals("刪除列"))
{
int columncount = defaultModel.getColumnCount()-1;
if(columncount >= 0)//若columncount<0代表已經沒有任何列了。
{
TableColumnModel columnModel = table.getColumnModel();
TableColumn tableColumn = columnModel.getColumn(columncount);
columnModel.removeColumn(tableColumn);
defaultModel.setColumnCount(columncount);
}
}
if(e.getActionCommand().equals("刪除行"))
{
int rowcount = defaultModel.getRowCount()-1;//getRowCount返回行數,rowcount<0代表已經沒有任何行了。
if(rowcount >= 0)

}
table.revalidate();
}

public static void main(String args[]) {
new AddRemoveCells();
}
}
JTable使用事例
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.util.*;

public class SimpleTable {
public SimpleTable() {
/**//*表格列向量*/
Vector cell ;
/**//*表格行向量*/
Vector row = new Vector();
/**//*聲明表格模型*/
DefaultTableModel tableModel = new DefaultTableModel();
/**//*聲明表格頭數組*/
String[] tableHeads = {"ID","姓名", "年齡", "城市"};
/**//*將表格頭轉換過向量類型,以備表格模型使用*/
Vector tableHeadName = new Vector();
for (int i = 0; i < tableHeads.length; i++) {
tableHeadName.add(tableHeads[i]);
}
/**//*初始化表格數據,這些數據實例運行來源於數據庫中*/
for (int i = 1; i <= 100; i++) {
cell = new Vector();
cell.add("" + i);
cell.add(" shit"+i);
cell.add(" 22");
cell.add(" 上海");
row.add(cell);
}
/**//*設置表格模型*/
tableModel.setDataVector(row, tableHeadName);
/**//*表格使用模型*/
JTable table = new JTable(tableModel);
table.setRowHeight(20);
/**//*new Cursor(1)設置鼠標指針樣式,12爲手形*/
table.setCursor(new Cursor(12));
table.setSelectionBackground(Color.black);
table.setSelectionForeground(Color.white);
table.setGridColor(Color.black);
makeFace(table);
table.setBackground(new Color(206,120,50));
table.setCellSelectionEnabled(false);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setCursor(new Cursor(12));
this.getContentPane().add(scrollPane);
this.setTitle("使用JTable表格的例子");
this.setSize(400, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}

/**//*表格間隔色顯示方法*/
public static void makeFace(JTable table) {

try {
DefaultTableCellRenderer tcr = new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if (row % 2 == 0)
setBackground(Color.white); /**//*設置奇數行底色*/
else if (row % 2 == 1)
setBackground(new Color(206, 231, 255)); /**//*設置偶數行底色*/
return super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
}
};
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(table.getColumnName(i)).setCellRenderer(tcr);
}
} catch (Exception ex) {
ex.printStackTrace();
}

}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章