天天看點

Swing之JTable的詳細介紹[zone yan]

[zone yan]下載下傳資源中有源碼下載下傳,其中包含了:

table中插入combobox,并能夠根據條件動态修改某一行的combobox中可選項

表格(Table)的使用與介紹

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

}

}