zeyuphoenix

          愿我愛的人快樂,愿愛我的人快樂,為了這些,我愿意不快樂.

          表格(排序)

          JTable的單元格和表頭寫完之后,關于JTable就剩下排序和過濾了,對于過濾來說,簡單的直接使用SunRowSorter就可以了,復雜的可以集成Lucence等排序工具,對于它來說,性能比實現更重要,有時間就開個專題寫,沒時間就不寫了,這里主要寫排序.

          排序從界面表現看其實就是對JTableHeader的鼠標操作,引發TableModel的數值比較,最后表現到畫面的過程,知道這個過程很重要,它可以幫助我們完全實現自己的排序過程.

          對于JavaJTable排序來說,主要分為兩個階段:Java1.6以前和Java1.6版本:Java1.6之前想要實現JTable的話,必須自己實現TableSorter,然后對JTableHeader去注冊,很麻煩,但是可以完全自己控制;Java1.6為了方便,Sun增加了排序和過濾的類:

          javax.swing.table. TableRowSorter<M extends TableModel> -à

          javax.swing. DefaultRowSorter<M, I> -à

          javax.swing. RowSorter<M>

          我們可以直接使用了.

          實現很容易,Sun官方的例子:

          RowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(table.getModel());

          table.setRowSorter(rowSorter);

          這是JTable就自動為你實現了過濾,它的好處是不污染任何的JTable數據和渲染,自然進行排序,結果如圖:

          但是對于默認的JTable來說, TableRowSorter的默認排序都是把數據當做Object來處理的,這時我們看表格的數據行:

          對于年份來說,這個排序是不對的,這個時候我們必須要復寫TableModelgetColumnClass方法,告訴TableRowSorter我們現在需要排序的數據類型, TableRowSorter就會根據類型給我們的列設置合適的比較器Comparator

          Collator.getInstance()

                 @Override

                  public Class<? extends Object> getColumnClass(int c) {

                      return getValueAt(0, c).getClass();

                  }

          這是對JTable的排序就完成了:

          但有時候還有別的情況,比如我們單元格放置的是一個特殊組件, TableRowSorter根本沒有合適的比較器給我們提供,或者是基本類型但是我們不希望使用默認的比較器Comparator,這個時候我們就需要自己實現一個Comparator,然后通過TableRowSortersetComparator設置某一列一個新的比較器.比如我們希望我們的第二列按字符串的反序排序:

          TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(table.getModel());

              rowSorter.setComparator(1, new Comparator<String>() {

                      @Override

                      publicint compare(String str1, String str2) {

                          return -str1.compareTo(str2);

                      }

                  });

          table.setRowSorter(rowSorter);

          效果如圖:

          到此為止,Java1.6排序的基本使用就完成了,通過Sun的方法很簡單就實現了.

          Java1.6以前的JTable排序功能必須自己實現,Sun官方也提供了例子,當然在1.6里你也可以自己實現,但是自己實現必須考慮排序Model,排序狀態,JTableHeader的狀態和監聽,還要自己寫HeaderRnederer,所以不是不能用1.6的話,最好不要自己實現.先看看是如何實現的,因為是Sun官方給的例子,就大概寫下,算是學習和回憶以前使用1.5自己寫Sorter的日子了.

          效果和1.6類似:

          首先看TableSorter,它繼承AbstractTableModel,這樣它也就相當于自己也是一種底層數據模型,可以記錄數據和排序數據:

          publicclass TableSorter extends AbstractTableModel {

          然后看它的屬性:

              private JTableHeader tableHeader;

          這個是需要排序的JTableHeader,這里需要對它進行鼠標監聽和狀態管理.

              private MouseListener mouseListener;

          private TableModelListener tableModelListener;

          這兩個是鼠標監聽器和TableModel監聽器,主要是當鼠標排序和JTabel數據變化時排序也隨之變化.

              private Map<Class<?>, Comparator<?>> columnComparators

                  = new HashMap<Class<?>, Comparator<?>>();

              private List<Directive> sortingColumns

                  = new ArrayList<Directive>();

          這連個主要是記錄狀態的,一個是記錄列的排序比較器,一個是記錄列的排序狀態.

          publicstaticfinal Comparator<Object> LEXICAL_COMPARATOR = new Comparator<Object>() {

                      publicint compare(Object o1, Object o2) {

                          return o1.toString().compareTo(o2.toString());

                      }

              };

          另外還提供了幾種基本的排序比較器,這是String的比較器.

          然后是是構造函數,

          public TableSorter(TableModel tableModel) {

          傳入我們需要排序的JTableTableModel,并對JTable增加事件監聽和TableModel數據變化監聽:

             this.tableHeader.addMouseListener(mouseListener);

             this.tableHeader.setDefaultRenderer(new SortableHeaderRenderer(

                              this.tableHeader.getDefaultRenderer()));

          this.tableModel.addTableModelListener(tableModelListener);

          然后處理這些監聽:

              privateclass MouseHandler extends MouseAdapter {

                  @Override

                  publicvoid mouseClicked(MouseEvent e) {

          首先取得排序列和當前排序狀態:

              JTableHeader h = (JTableHeader) e.getSource();

                      TableColumnModel columnModel = h.getColumnModel();

              int viewColumn = h.columnAtPoint(e.getPoint());

              int column = columnModel.getColumn(viewColumn).getModelIndex();

          int status = getSortingStatus(column);

          然后判斷后調用排序方法:

          setSortingStatus(column, status);

          TableModel數據變化監聽也類似:

              privateclass TableModelHandler implements TableModelListener {

                  @Override

                  publicvoid tableChanged(TableModelEvent e) {

          非排序狀態直接插入:

           if (!isSorting()) {

                          clearSortingState();

                          fireTableChanged(e);

                          return;

           }

          排序狀態比較插入:

             int column = e.getColumn();

             if (e.getFirstRow() == e.getLastRow()

                  && column != TableModelEvent.ALL_COLUMNS

                  && getSortingStatus(column) == NOT_SORTED

                  && modelToView != null) {

                    int viewIndex = getModelToView()[e.getFirstRow()];

                    fireTableChanged(new TableModelEvent(TableSorter.this,

                                  viewIndex, viewIndex, column, e.getType()));

                          return;

            }

          然后是一個行的比較器:

              // Helper classes

          privateclass Row implements Comparable<Object> {

          它取得比較的行:

                  @Override

                  publicint compareTo(Object o) {

                      int row1 = modelIndex;

                      int row2 = ((Row) o).modelIndex;

          再去的比較的值:

                Object o1 = tableModel.getValueAt(row1, column);

                Object o2 = tableModel.getValueAt(row2, column);

          根據我們提供的構造器比較:

          comparison = getComparator(column).compare(o1, o2);

          其它的還有一些設置比較器,設置JTableHeaderRenderer,繪制排序的圖標的方法,基本都是以前JTable會學習到的,就不寫了,很多但是不難.

          然后是使用,先創建我們自己構造的TableSorter:

          TableSorter sorter = new TableSorter(new MyTableModel());

          當做JTableTableModel放入JTable中:

          JTable table = new JTable(sorter);

          還要設置一下Header,目的是使用我們自己做成的HeaderRenderer,可以出現圖標

          sorter.setTableHeader(table.getTableHeader());

          以后就和正常JTable一樣了.

          最后,我們看一個我們自己實現排序比較和Renderer的例子:

          工程目錄如下:

          其中和類是實現了Icon接口的繪制JTableHeader排序時的圖片的類,

          publicclass MyBlankIcon implements Icon {

          publicclass MySortIcon implements Icon {

          主要過程就是實現paintIcon方法繪制圖片,前面寫過這種三角形形式的圖片繪制方法了,這里省略.

          void paintIcon(Component c, Graphics g, int x, int y);

          然后就是比較重要的MyTableSorter,它繼承TableRowSorter,擴充了我們自己的排序實現:

          publicclass MyTableSorter extends TableRowSorter<TableModel> {

          提供了三個方法,正序、逆序和無序:

              /**

               * Enumeration value indicating the items are sorted in increasing

               */

              protectedvoid setASCSort(int colIdx) {

                  ArrayList<SortKey> key = new ArrayList<SortKey>();

                  key.add(new RowSorter.SortKey(colIdx, SortOrder.ASCENDING));

                  setSortKeys(key);

              }

              /**

               * Enumeration value indicating the items are sorted in decreasing * order.

               */

              protectedvoid setDESCSort(int colIdx) {

                  ArrayList<SortKey> key = new ArrayList<SortKey>();

                  key.add(new RowSorter.SortKey(colIdx, SortOrder.DESCENDING));

                  setSortKeys(key);

              }

              /**

               * Enumeration value indicating the items are unordered.

               */

              protectedvoid setUNSort(int colIdx) {

                  ArrayList<SortKey> key = new ArrayList<SortKey>();

                  key.add(new RowSorter.SortKey(colIdx, SortOrder.UNSORTED));

                  setSortKeys(key);

              }

          提供設置當前排序狀態的方法:

              protectedvoid setSorterStatus(int column, boolean CtrlDown) {

              List<SortKey> SortStatus = new ArrayList<SortKey>(getSortKeys());

                  SortKey sortKey = null;

                  int sortIndex = -1;

                  for (sortIndex = SortStatus.size() - 1; sortIndex >= 0; sortIndex--) {

                      if (SortStatus.get(sortIndex).getColumn() == column) {

                          break;

                      }

                  }

                  if (sortIndex == -1) {

                      // Key doesn't exist

                      if (CtrlDown) {

                          sortKey = new SortKey(column, SortOrder.DESCENDING);

                      } else {

                          sortKey = new SortKey(column, SortOrder.ASCENDING);

                      }

                      SortStatus.add(0, sortKey);

                  } elseif (sortIndex == 0) {

                      // It's the primary sorting key, toggle it

                      SortStatus.set(0, toggle(SortStatus.get(0), CtrlDown));

                  } else {

                      // It's not the first, but was sorted on, remove old

                      // entry, insert as first with ascending.

                      SortStatus.remove(sortIndex);

                      if (CtrlDown) {

                          sortKey = new SortKey(column, SortOrder.DESCENDING);

                      } else {

                          sortKey = new SortKey(column, SortOrder.ASCENDING);

                      }

                      SortStatus.add(0, sortKey);

                  }

                  if (SortStatus.size() > getMaxSortKeys()) {

                      SortStatus = SortStatus.subList(0, getMaxSortKeys());

                  }

                  setSortable(column, true);

                  setSortKeys(SortStatus);

                  setSortable(column, false);

              }

          提供取得下一個狀態的方法:

              protected SortKey toggle(SortKey key, boolean CtrlDown) {

                  if (key.getSortOrder() == SortOrder.ASCENDING) {

                   returnnew SortKey(key.getColumn(), SortOrder.DESCENDING);

                  } elseif (key.getSortOrder() == SortOrder.DESCENDING) {

                      returnnew SortKey(key.getColumn(), SortOrder.UNSORTED);

                  } else {

                      returnnew SortKey(key.getColumn(), SortOrder.ASCENDING);

                  }

              }

          然后就是Renderer方法了,它繼承TableCellRenderer,設置排序狀態和Header狀態:

          publicclass MyHeaderButtonRenderer extends JButton implements

                  TableCellRenderer, MouseListener {

          它提供一個屬性存儲當前列的排序狀態:

              /** save the header state. */

              private Hashtable<Integer, Integer> state = null;

          在它的鼠標事件里,設置排序和排序狀態:

              /**

               * Invoked when the mouse button has been clicked (pressed and

           * released) on a component.

               */

              @Override

              publicvoid mouseClicked(MouseEvent e) {

          先取得鼠標事件的列,設置表現:

                int col = header.columnAtPoint(e.getPoint());

                int sortCol = header.getTable().convertColumnIndexToModel(col);

                renderer.setPressedColumn(col);

                renderer.setSelectedColumn(col);

                header.repaint();

          再設置排序和狀態:

          if (header.getTable().isEditing()) {

                       header.getTable().getCellEditor().stopCellEditing();

                }

                if (!(DOWN == renderer.getState(col))

                         && !(UP == renderer.getState(col))) {

                      sorter.setUNSort(sortCol);

                }

          實現TableCellRenderer的方法設置列的Header的表現:

          @Override

          public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

          if (header != null && renderer != null) {

                      boolean isPressed = (column == pushedColumn);

                      button.getModel().setPressed(isPressed);

                      button.getModel().setArmed(isPressed);

                  }

          使用也不是很麻煩:

          先創建Sorter:

          TableSorter tableSorter = new MyTableSorter(table);

          設置某一列的比較器,TableSorter一樣:

          tableSorter.setComparator(2, new MyComparator<String>());

           table.setRowSorter(tableSorter);

          然后是創建Renderer:

          MyHeaderButtonRenderer renderer = new MyHeaderButtonRenderer();

          然后設置JTableHeaderRenderer:

           table.getColumnModel().getColumn(i).setHeaderRenderer(renderer)

          這樣就完成了.

          posted on 2010-04-15 21:11 zeyuphoenix 閱讀(3725) 評論(0)  編輯  收藏 所屬分類: JTable的使用

          導航

          <2010年4月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          統計

          常用鏈接

          留言簿(52)

          隨筆分類

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 浦江县| 古丈县| 新昌县| 合肥市| 衡阳县| 湾仔区| 武穴市| 岑溪市| 化隆| 尚志市| 开远市| 日喀则市| 启东市| 阜新市| 汨罗市| 和平县| 镇巴县| 玉门市| 永善县| 彭山县| 剑河县| 曲松县| 仙桃市| 常宁市| 五原县| 施秉县| 剑阁县| 平和县| 金塔县| 鄂伦春自治旗| 桐柏县| 呈贡县| 临朐县| 屯门区| 衢州市| 明光市| 临高县| 射洪县| 简阳市| 聂荣县| 平谷区|