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);
- }
- }
圖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;
- }
- };
JTable過濾
在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列即銷售列(字段包括“已售”、“預訂"、”未售“),
- if(displaySaleStatus==0&&displayBookStatus==0&&displayNotBookStatus==0)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("什么都不顯示哦", 4));
- if(displaySaleStatus==1&&displayBookStatus==0&&displayNotBookStatus==0)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("已售", 4));
- else if(displaySaleStatus==0&&displayBookStatus==1&&displayNotBookStatus==0)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("預訂", 4));
- else if(displaySaleStatus==0&&displayBookStatus==0&&displayNotBookStatus==1)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("未訂", 4));
- else if(displaySaleStatus==1&&displayBookStatus==1&&displayNotBookStatus==0)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("已售|預訂", 4));
- else if(displaySaleStatus==0&&displayBookStatus==1&&displayNotBookStatus==1)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("預訂|未訂", 4));
- else if(displaySaleStatus==1&&displayBookStatus==0&&displayNotBookStatus==1)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("已售|未訂", 4));
- else if(displaySaleStatus==1&&displayBookStatus==1&&displayNotBookStatus==1)
- ((TableRowSorter)this.table.getRowSorter()).setRowFilter(RowFilter.regexFilter("已售|預訂|未訂", 4));//全部顯示,或setRowFilter(null)
一下是地震發布系統中過濾第2列即震級列(字段為Float型)
- /**
- * (大、中、小地震)顯示按鈕事件處理過程
- * */
- @SuppressWarnings("unchecked")
- private void showActionHandle(){
- boolean showBigEqStatus=showBigEqBut.isSelected();
- boolean showMiddleEqStatus=showMiddleEqBut.isSelected();
- boolean showSmallEqStatus=showSmallEqBut.isSelected();
- if(showBigEqStatus==false&&showMiddleEqStatus==false&&showSmallEqStatus==false)
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.AFTER, 100,2));
- if(showBigEqStatus==true&&showMiddleEqStatus==false&&showSmallEqStatus==false){
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.AFTER,TableAttribute.BIG_EARTHQUAKE_THRESHOLD,2));
- }
- else if(showBigEqStatus==false&&showMiddleEqStatus==true&&showSmallEqStatus==false){
- List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
- filters.add(RowFilter.numberFilter(ComparisonType.AFTER,TableAttribute.MIDDLE_EARTHQUAKE_THRESHOLD,2));
- filters.add(RowFilter.numberFilter(ComparisonType.BEFORE,TableAttribute.BIG_EARTHQUAKE_THRESHOLD,2));
- RowFilter<Object,Object> fooBarFilter = RowFilter.andFilter(filters);
- ((TableRowSorter)this.getRowSorter()).setRowFilter(fooBarFilter);
- }
- else if(showBigEqStatus==false&&showMiddleEqStatus==false&&showSmallEqStatus==true){
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.BEFORE,TableAttribute.MIDDLE_EARTHQUAKE_THRESHOLD,2));
- }
- else if(showBigEqStatus==true&&showMiddleEqStatus==true&&showSmallEqStatus==false){
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.AFTER,TableAttribute.MIDDLE_EARTHQUAKE_THRESHOLD,2));
- }
- else if(showBigEqStatus==false&&showMiddleEqStatus==true&&showSmallEqStatus==true){
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.BEFORE,TableAttribute.BIG_EARTHQUAKE_THRESHOLD,2));
- }
- else if(showBigEqStatus==true&&showMiddleEqStatus==false&&showSmallEqStatus==true){
- List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
- filters.add(RowFilter.numberFilter(ComparisonType.AFTER,TableAttribute.BIG_EARTHQUAKE_THRESHOLD,2));
- filters.add(RowFilter.numberFilter(ComparisonType.BEFORE,TableAttribute.MIDDLE_EARTHQUAKE_THRESHOLD,2));
- RowFilter<Object,Object> fooBarFilter = RowFilter.orFilter(filters);
- ((TableRowSorter)this.getRowSorter()).setRowFilter(fooBarFilter);
- }
- else if(showBigEqStatus==true&&showMiddleEqStatus==true&&showSmallEqStatus==true){
- ((TableRowSorter)this.getRowSorter()).setRowFilter(RowFilter.numberFilter(ComparisonType.AFTER, 0,2));
- }
- }
補充:將表格視圖中的行號映射到模型中對應的行號,才能正確地得到行的內容,尤其是自動排序后,視圖中的行號與表格模型中的行號不一致,TableModel中的方法getValueAt(row,column)中的row指模型中的row,而通過table.getSelectedRow()或者事件處理中通過table.rowAtPoint(e.getPoint())得到row指視圖中的row,因此必須將視圖中的row轉化為model中的row:
int view_row = table.rowAtPoint(e.getPoint()); //獲得視圖中的行索引
int view_col = table.columnAtPoint(e.getPoint()); //獲得視圖中的列索引
int model_row= table.convertRowIndexToModel(row);//將視圖中的行索引轉化為數據模型中的行索引
int model_col = table.convertColumnIndexToModel(col);//將視圖中的列索引轉化為數據模型中的列索引
本文轉自:http://blog.csdn.net/b_h_l/article/details/7771944
