<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    有才華的人,別忘記給滋潤你的那塊土壤施肥

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      28 隨筆 :: 5 文章 :: 147 評論 :: 0 Trackbacks
         為一個JList定制一個排序,可以繼承AbstractListModel,使用排序的容器如TreeSet就可以搞定,但是卻失去很多靈活性,如我要原始的排列呢?
    下面是一個好的處理,原文為:查看,下面是原文的一些大致介紹:

        這篇文章提供兩個類,一個是 SortedListModel 繼承于AbstractListModel實現(xiàn)排序等操作,一個SortedListModelDemo為SortedListModel測試用
     
         該SortedListModel類是一個裝飾類,實行排序的所有功能。 該SortedListModelDemo類包含的應用程序演示如何使用SortedListModel 。
         那么一個ListModel的裝飾類, SortedListModel類應該有如下功能:
        1、使用裝飾設計模式為任何ListModel對象提供排序 
        2、 提供在排序和無序之間的映射 
        3、允許程序員為自己提供java.util.Comparator對象比較模型元素 
        4、 提供升,降,和無序排序
        5、需要最低限度的更新現(xiàn)有的應用程序代碼
        如下圖:該演示一個Jlist組件,包括一組排序類型選擇的radio,和增加,刪除按鈕,當然你也可以整的更復雜一些。


    SortedListModel

    在JDK1.6中為Jtable提供了排序和篩選的功能:TableRowSorter,這個類的行為就像裝飾器,為table model操作的時候排序,然而這相同的功能卻沒有提供給Jlist類,但是這里我們可以子創(chuàng)建一個SortListModel類,為ListModel提供排序功能。

    因為SortedListModel對象必須包裝ListModel對象,所以它至少應執(zhí)行相同的接口。同時,也要支持分發(fā)數(shù)據(jù)監(jiān)聽事件,這里將SortedListModel繼承javax.swing.AbstractListModel類,這個類可以方便的管理及通知ListDataListener對象。

    SortedListModel構造函數(shù):
    通常一個裝飾器通過構造函數(shù)對其傳入的對象進行包裝,所以SortedListModel需要傳入原始的ListModel對象,以便對通過原始的model而調用一些方法。由于要進行升序,降序,以及無序的三種狀態(tài),所以傳入一個排序SortOrder對象,最后還需要一個Comparator對象,來對你的Model進行怎樣的排序:
    代碼如下:

        public SortedListModel(ListModel model, SortOrder sortOrder, Comparator comp) {
            unsortedModel 
    = model;
            unsortedModel.addListDataListener(
    new ListDataListener() {
                
    public void intervalAdded(ListDataEvent e) {
                    unsortedIntervalAdded(e);
                }

                
    public void intervalRemoved(ListDataEvent e) {
                    unsortedIntervalRemoved(e);
                }

                
    public void contentsChanged(ListDataEvent e) {
                    unsortedContentsChanged(e);
                }
        
            }
    );
            
    this.sortOrder = sortOrder;
            
    if (comp != null{
                comparator 
    = comp;
            }
     else {
                comparator 
    = Collator.getInstance();
            }
          
            
    // get base model info
            int size = model.getSize();
            sortedModel 
    = new ArrayList<SortedListEntry>(size);
            
    for (int x = 0; x < size; ++x) {
                SortedListEntry entry 
    = new SortedListEntry(x);
                
    int insertionPoint = findInsertionPoint(entry);
                sortedModel.add(insertionPoint, entry);
            }

        }

    在上面的代碼中,首先保存對原始的model,因為要它為增加、刪除、改變里面的列的時候需要做出相應的反應,為原始的model添加事件監(jiān)聽,設置Comparator,當沒有提供Comparator的時候,創(chuàng)建一個默認的Comparator,最后構建一個ArrayList來存入原始的model元素的索引來進行排序。

    至此:這個SortedListModel對象具有如下特性:
    它有一個原始model的參照。
    它有用戶排序方式。
    它有一個Comparator對model的內(nèi)容進行排序。
    它有原始model的一個排序代理。

    SortedListModel提供了一個SortOrder的內(nèi)部類,來表示排序的方式。SortOrder是一個枚舉,代碼如下:

        public enum SortOrder {
            UNORDERED,
            ASCENDING,
            DESCENDING;
        }
    那么原始的model和經(jīng)過排序后的一種對應關系先給出圖,如下:

    下面是SortedListEntry類的一個比較方法,用它來對Model中的元素進行排序,SortedListModel使用java.text.Collortor來比較。她只能用來比較String,如果你的model是其他對象,那么提供自己的Comparator,如果沒有的話,則SortedListModel將會調用model的元素的toString方法來進行比較。
            
            
    public int compareTo(Object o) {
                
    // retrieve the element that this entry points to
                
    // in the original model
                Object thisElement = unsortedModel.getElementAt(index);
                SortedListEntry thatEntry 
    = (SortedListEntry)o;
                
    // retrieve the element that thatEntry points to in the original
                
    // model
                Object thatElement = unsortedModel.getElementAt(thatEntry.getIndex());
                
    if (comparator instanceof Collator) {
                    thisElement 
    = thisElement.toString();
                    thatElement 
    = thatElement.toString();
                }

                
    // compare the base model's elements using the provided comparator
                int comparison = comparator.compare(thisElement, thatElement);
                
    // convert to descending order as necessary
                if (sortOrder == SortOrder.DESCENDING) {
                    comparison 
    = -comparison;
                }

                
    return comparison;
            }

      

    那么什么時候程序會調用這個compareTo方法呢?當你增加或改變這個排序時的model的時候,如下面這個findInsertionPoint方法使用Collections的二分查找對應的位置來插入一個元素,就會調用這個compareTo方法,代碼如下:

     private int findInsertionPoint(SortedListEntry entry) {
            
    int insertionPoint = sortedModel.size();
            
    if (sortOrder != SortOrder.UNORDERED)  {
                insertionPoint 
    = Collections.binarySearch((List)sortedModel, entry);
                
    if (insertionPoint < 0{
                    insertionPoint 
    = -(insertionPoint +1);
                }

            }

            
    return insertionPoint;
        }


    當取得一個元素的時候,不一定就是你在界面上所看到的位置,那么getElementAt方法則要做相應的處理,因為這個排序只是記錄排序后的索引指,這個index要做相應的處理,如下:
        public Object getElementAt(int index) throws IndexOutOfBoundsException {
            
    int modelIndex = toUnsortedModelIndex(index);
            Object element 
    = unsortedModel.getElementAt(modelIndex);
            
    return element;
        }

    事件處理:
    為原始的model添加事件監(jiān)聽,對數(shù)據(jù)的增加、刪除,修改進行監(jiān)聽,如上面給出的構造函數(shù)的代碼所示,注冊一個ListDataListenter對象,這個匿名類包括以下幾個方法,如:
            unsortedModel.addListDataListener(new ListDataListener() {
                
    public void intervalAdded(ListDataEvent e) {
                    unsortedIntervalAdded(e);
                }

                
    public void intervalRemoved(ListDataEvent e) {
                    unsortedIntervalRemoved(e);
                }

                
    public void contentsChanged(ListDataEvent e) {
                    unsortedContentsChanged(e);
                }
        
            }
    );
    unsortedIntervalAdded方法相對來比較復雜點,當原始未排序的model添加一個新的元素的時候,它要提供一個插入元素的開始和結束的索引,雖然這些索引在原始的model中是連續(xù)的數(shù)字,但是這些索引在已排序后的model卻不上一樣的,如上面的圖可知,所增加一個新的元素的時候,需要進行相對應的處理,代碼如下:
       private void unsortedIntervalAdded(ListDataEvent e) {
            
    int begin = e.getIndex0();
            
    int end = e.getIndex1();
            
    int nElementsAdded = end-begin+1;
            
            
    /* Items in the decorated model have shifted in flight.
             * Increment our model pointers into the decorated model.
             * We must increment indices that intersect with the insertion
             * point in the decorated model.
             
    */

            
    for (SortedListEntry entry: sortedModel) {
                
    int index = entry.getIndex();
                
    // if our model points to a model index >= to where
                
    // new model entries are added, we must bump up their index
                if (index >= begin) {
                    entry.setIndex(index
    +nElementsAdded);
                }

            }

            
            
    // now add the new items from the decorated model
            for (int x = begin; x <= end; ++x) {
                SortedListEntry newEntry 
    = new SortedListEntry(x);
                
    int insertionPoint = findInsertionPoint(newEntry);
                sortedModel.add(insertionPoint, newEntry);
                fireIntervalAdded(ListDataEvent.INTERVAL_ADDED, insertionPoint, insertionPoint);
            }

    }

    unsortedIntervalRemoved方法原理類似,這里就不給出代碼,詳見附件。
    你的應用程序注冊接受到了Jlist的事件通知的時候,如ListSelectionEvent的時候,這時候選擇的元素是已經(jīng)排完序的一個元素,所以要提供一個返回原始model索引的方法,要進行正確的處理,在getElementAt方法方法就調用了下面的方法,代碼如下:
    public int toUnsortedModelIndex(int index) throws IndexOutOfBoundsException {
            
    int modelIndex = -1;
            SortedListEntry entry 
    = sortedModel.get(index);
            modelIndex 
    = entry.getIndex();
            
    return modelIndex;
            
        }

      使用這個SortedListModel,只需要在你的應用程序中做一下三個步驟:

    1、創(chuàng)建一個SortedListModel對象

    2、將這個SortedListModel對象添加到Jlist組件中

    3、注意排序后和未排序的model元素所對應的關系

    所以在你的程序中只需要以下幾句代碼而已:
     

    unsortedModel = new DefaultListModel();
    sortedModel 
    = new SortedListModel(unsortedModel);
    list.setModel(sortedModel);

    如上面第三條所說,有點處理得做一些額外處理,下面是一個刪除方法得做出如下的一些處理:

     private void btnDeleteSelectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteSelectionActionPerformed
            int[] sortedSelection = list.getSelectedIndices();
            
    int[] unsortedSelection = sortedModel.toUnsortedModelIndices(sortedSelection);
            
            
    for (int x = unsortedSelection.length - 1; x >= 0--x) {
                unsortedModel.remove(unsortedSelection[x]);
            }

        }


    PS:原文提供的代碼的測試代碼的布局用了一些Jdesktop類的引用,我做了一些改變,需要的朋友可以在這里下載 
    posted on 2008-12-20 18:52 kissjava 閱讀(4222) 評論(3)  編輯  收藏 所屬分類: swing

    評論

    # re: 一個可排序的JList 2008-12-26 22:40 Qil.Wong
    換我實現(xiàn),不會搞這么復雜,直接使用Collections.sort(list),最后更新model就行  回復  更多評論
      

    # re: 一個可排序的JList 2008-12-27 15:22 枯寬
    @Qil.Wong
    正如開篇所說的第五條:需要最低限度的更新現(xiàn)有的應用程序代碼
      回復  更多評論
      

    # re: 一個可排序的JList 2010-05-12 13:33 師大
    @Qil.Wong
    要是我的話也這樣。  回復  更多評論
      

    主站蜘蛛池模板: 精品国产亚洲一区二区三区| 最好免费观看韩国+日本 | mm1313亚洲国产精品美女| 国产日产亚洲系列最新| 亚洲AV永久无码区成人网站| 亚洲性69影院在线观看| 自拍偷区亚洲国内自拍| 国产黄色免费观看| 午夜免费福利视频| 美女被免费视频网站a国产 | 免费大黄网站在线看| 亚洲国产精品热久久| 亚洲乱理伦片在线观看中字| 你懂的网址免费国产| 成年女人免费碰碰视频| 国产偷国产偷亚洲清高动态图| 亚洲综合激情五月丁香六月| 人妻无码久久一区二区三区免费| 国产成人免费全部网站| 亚洲人成电影网站| 免费av片在线观看网站| 国产婷婷高清在线观看免费| 色婷婷综合缴情综免费观看| 永久免费av无码网站韩国毛片| 亚洲无线码在线一区观看| 另类图片亚洲校园小说区| 最近高清中文字幕免费| 伊人久久大香线蕉亚洲| 免费A级毛片av无码| 亚洲第一综合天堂另类专| 国产免费的野战视频| 亚洲综合伊人久久综合| 亚洲成人免费在线| 亚洲成av人在线观看网站| 亚洲男人的天堂在线va拉文| 国产精品亚洲色图| 亚洲Aⅴ无码专区在线观看q| a级毛片在线免费看| 亚洲视频无码高清在线| 国产亚洲精品福利在线无卡一| 1000部拍拍拍18免费网站|