表格(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
    for (int j=0;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
  for (int j=0;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
{
  for(int j=0; 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();
}
}

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()