在這篇文章中我接著介紹另外幾種新的GUI功能。這些功能是:
·帶有排序和過濾功能的JTable。
·增強的JTabbedPane組件
·增強的打印功能
·增強的拖放功能
帶有排序和過濾功能的JTable 在Java SE 6中除了java.awt被更新外,javax.swing同時也有了很大的改進。在C/S程序中我們會經常使用到"表"。如我們可以在查詢數據庫後將查詢結果顯示在表格中。在Java中顯示表格使用的是JTable類。在以前的版本中,JTable只能簡單地顯示數據,並沒有什麼附加的處理功能,而在Java SE 6中的JTable增加了排序和過濾功能。用戶可以單擊列頭進行排序,也可以根據某一列來過濾表中的數據。
為了使JTable可以對數據進行,必須將RowSorter類和JTable進行關聯。RowSorter是一個抽象類,它負責將JTable中的數據映射成可排序的數據。在真正使用時,我們將直接使用RowSorter的子類TableRowSorter。下面的代碼顯示了如何將TableRowSorter類和JTable相關聯。
TableModel model = new DefaultTableModel(rows, columns);
JTable table = new JTable(model);
RowSorter sorter = new TableRowSorter(model);
table.setRowSorter(sorter);
上面代碼首先建立一個TableModel,然後將這個TableModel的實例同時傳遞給了JTable和RowSorter。下面是一個使用JTable排序的簡單的例子。
import Javax.swing.*;
import Javax.swing.table.*;
import Java.awt.*;
public class TestSortedTable
{
public static void main(String args[])
{
JFrame frame = new JFrame("JTable的排序測試");
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
// 表格中顯示的數據
Object rows[][] =
{
{ "王明", "中國", 44 },
{ "姚明", "中國", 25 },
{ "趙子龍", "西蜀", 1234 },
{ "曹操", "北魏", 2112 },
{ "Bill Gates", "美國", 45 },
{ "Mike", "英國", 33 } };
String columns[] =
{ "姓名", "國籍", "年齡" };
TableModel model = new DefaultTableModel(rows, columns);
JTable table = new JTable(model);
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
frame.add(pane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
圖1和圖2分別是按"姓名"進行升序和降序排列的顯示結果。
圖1 按"姓名"升序顯示
圖2 按"姓名"降序顯示
圖3顯示的是按"年齡"進行降序排列。但我們發現一個奇怪的問題,就是"年齡"字段並不是按數值類型進行排序的,而是按字符類型進行排序的。
圖3 按年齡降序顯示
出現這種情況是因為在默認情況下DefaultTableModal的列是Object類型。而要想使JTable按數值進行排序,必須要覆蓋DefaultTableModal的getColumnClass方法。
TableModel model = new DefaultTableModel(rows, columns)
{
public Class getColumnClass(int column)
{
Class returnValue;
if ((column >= 0) && (column < getColumnCount()))
{
returnValue = getValueAt(0, column).getClass();
}
else
{
returnValue = Object.class;
}
return returnValue;
}
};
圖4顯示了按"年齡"進行排序的界面,看看,是不是按數值進行排序了。
圖4 按數值類型進行排序 下面讓我們來看看來何使用JTable進行過濾。我們可以通過convertRowIndexToModel方法進行過濾。下面的代碼加在一個按鈕中添加事件代碼調用JTable的過濾功能。
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String text = filterText.getText();
if (text.length() == 0)
{
sorter.setRowFilter(null);
}
else
{
sorter.setRowFilter(RowFilter.regexFilter(text));
}
}
});
上面的代碼並沒有調用convertRowIndextoModel()方法,如果調用它,你就可以在表中進行相應的操作。
在JTable中通過抽象類RowFilter類對行進行過濾。和排序不同,你可以不建立它們的子類,而使用這個抽象類的6個靜態方法。
·andFilter
·dateFilter(RowFilter.ComparisonType type, Date date, int... indices)
·notFilter(RowFilter<M,I> filter)
·numberFilter(RowFilter.ComparisonType type, Number number, int... indices)
·orFilter
·regexFilter(String regex, int... indices)
其中andFilter()、orFilter()以及notFilter()方法的功能是將當前的過濾條件和其它的過濾條件進行組合。如在同時比較日期和數值時需要將日期過濾和數值過濾進行組合。這些組合是非常簡單的。
RowFilter的類型比較允許你進行4種關系的比較,等於、不等於、大於或小於。我們可以通過指定某一列進行過濾,也可以對所有的列進行過濾。這其中最為有趣的也許是正則表達式過濾(regular expression filter,或簡稱為regex filter)。使用這個過濾器可以對表中數據進行更高級的過濾。下面是實現一個簡單過濾器的代碼。
import Javax.swing.*;
import Javax.swing.table.*;
import Java.awt.*;
import Java.awt.event.*;
public class TestFilter
{
public static void main(String args[])
{
JFrame frame = new JFrame("JTable的過濾測試");
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
Object rows[][] =
{
{ "王明", "中國", 44 },
{ "姚明", "中國", 25 },
{ "趙子龍", "西蜀", 1234 },
{ "曹操", "北魏", 2112 },
{ "Bill Gates", "美國", 45 },
{ "Mike", "英國", 33 } };
String columns[] =
{ "姓名", "國籍", "年齡" };
TableModel model = new DefaultTableModel(rows, columns)
{
public Class getColumnClass(int column)
{
Class returnValue;
if ((column >= 0) && (column < getColumnCount()))
{
returnValue = getValueAt(0, column).getClass();
}
else
{
returnValue = Object.class;
}
return returnValue;
}
};
final JTable table = new JTable(model);
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
frame.add(pane, BorderLayout.CENTER);
JPanel panel = new JPanel(new BorderLayout());
JLabel label = new JLabel("過濾");
panel.add(label, BorderLayout.WEST);
final JTextField filterText = new JTextFIEld("");
panel.add(filterText, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
JButton button = new JButton("過濾");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String text = filterText.getText();
if (text.length() == 0)
{
sorter.setRowFilter(null);
}
else
{
sorter.setRowFilter(RowFilter.regexFilter(text));
}
}
});
frame.add(button, BorderLayout.SOUTH);
frame.setSize(300, 250);
frame.setVisible(true);
}
}
圖5是上面程序的運行界面。
圖 5