Tải bản đầy đủ - 0 (trang)
Hack 23. Let Your JTables Do the Sorting

Hack 23. Let Your JTables Do the Sorting

Tải bản đầy đủ - 0trang

toresortitscontentsandthenfireoffeventstoJTabletodrive

updatestotheonscreenrepresentation.

Therearemoredetailsintheactualimplementationofcourse,

particularlywhenitcomestodoingthesorting.Example3-5

showsthecodefortheSortableTableModel.



Example3-5.Self-sortingTableModel



















publicclassSortableTableModelimplementsTableModel,



TableModelListener{



EventListenerListlistenerList=newEventListe



TableModeldelegatedModel;



int[]sortedIndicies;



intsortColumn;



Comparatorcomparator;



Comparator[]comparators;































publicSortableTableModel(TableModeltm){



delegatedModel=tm;



delegatedModel.addTableModelListener(t



comparators=newComparator[tm.getCol



sortedIndicies=newint[0];



setSortColumn(0);



























}

//listenerstuff

publicvoidaddTableModelListener(TableModelLi



listenerList.add(TableModelListener.cl

}



















publicvoidremoveTableModelListener(TableMode



listenerList.remove(TableModelListener

}











publicvoidfireTableModelEvent(TableModelEven





















Object[]listeners=listenerList.getLi

for(inti=listeners.length-2;i>=0;



























if(listeners[i]==TableModelListener.class){



((TableModelListener)listeners[i+1]).t

}



}

}



































//contentsstuff

publicClassgetColumnClass(intcolumnIndex)



if(delegatedModel.getRowCount()>0)

returndelegatedModel.getValueAt(0,columnIndex



else

returnObject.class;

}















//getColumnCount(),getColumnName(),getRowCou

//getValueAt(),isCellEditable(),setValueAt()















//internalhelpers

publicvoidsetComparatorForColumn(Comparator



































//rangecheck



if(i>comparators.length){





Comparator[]newComparators=newCompa





System.arraycopy(comparators,0,







newComparators,0,







comparators.length);





comparators=newComparators;



}



//addthecomparator



comparators[i]=c;



}

publicvoidsetSortColumn(inti){



sortColumn=i;















































}



//resetcurrentcomparator,possiblytonull,

//willmakeususe"naturalordering"forthos

comparator=null;

if((comparators!=null)&&



(comparators.length>0))



//isthereoneinthelistofcomparat



comparator=comparators[sortColumn];



//nowdothesort

resort();











publicintgetSortColumn(){



returnsortColumn;

}



























//resort()methodlistedbelow

//SortingDelegateinnerclasslistedbelow

//SortingDelegateComparatorinnerclasslistedbelow







































publicvoidtableChanged(TableModelEvente){







switch(e.getType()){







caseTableModelEvent.DELETE:{







resort();







fireAllChanged();







break;







}





































caseTableModelEvent.INSERT:{

resort();

fireAllChanged();

break;

}

caseTableModelEvent.UPDATE:{

resort();

fireAllChanged();























}



break;











}











}











}



protectedvoidfireAllChanged(){



TableModelEvente=newTableModelEvent(this);



fireTableModelEvent(e);

}



Theinstancevariablesinthisclassincludealistofevent

listenerstosupporttheTableModelListenermethodsspecifiedby

theTableModelinterface,themodelpassedinbythecaller,amap

ofsortedindices,theindexofthecolumntosortby,thecurrent

Comparatortosortwith,andanarrayofComparatorsarrangedby

thecolumneachonesorts(thevaluemaybenullifthecolumn

isaprimitiveoranothertypethatdoesn'tneedacustom

Comparator).

ThesortedIndiciesarrayiscrucialtomaintainingtherelationship

betweenthetwotables.Thevaluesinthisarrayindicatea

mappedrowinthedelegatedModel.Thus,ifacallerasksfora

valueinrow2,thismodelwillgetthevalueofsortedIndicies[2]

andgetthatrowfromthedelegatedModel.Allthemethodsof

TableModelthatworkwithrowsgetValueAt(),isCellEditable(),and

setValueAt()usethislookup,sotherealkeytokeepingthe

modelworkingistokeepthismapaccurate,whichinturn

meanstoredothesort:

Wheneverthecontentsoftheunderlyingmodelchange

Wheneveracallerchangesthesortingcriteriaofthismodel



Theconstructorislargelytrivial,settingthedelegatedModel

instance,addingaTableModelListenertoitsothesortingmodel

canresortonupdatestothedelegatedModel'scontents,and

initializingthestructuresforthecomparatorsandtherow

mapping.Supportingthelistenersisalsoessentiallyboilerplate;

here,I'veusedtheEventListenerListandbackward-counting

eventfiring[Hack#94],asisdonecommonlythroughout

Swing.

TheimplementationofgetColumnClass()isimportant;itensures

thatTableCellRendererswillgetusedwhenappropriate.Swing's

implementationofAbstractTableModelliterallyjustreturns

Object.classinallcases,whichcauseseverythingtorenderas

JLabelsoftheObject'stoString().Yuck.Thisversionactuallylooks

atthedelegatedModeland,ifithasanydata,returnstheclassof

theobjectinthefirstrowofthedesignatedcolumn.

Nextinthesource,you'llfindaseriesofmethodsthatinvolve

thecontentsofthemodel:

getColumnCount()



getColumnName()



getrowCount()



getValueAt()



isCellEditable()



setValueAt()



Allofthesemethodsdelegatetothewrappedmodel,withthe

caveatthatanythatworkwithrowslookupthemappedrow

fromthesortedIndiciesarray,asseeninExample3-6.



Example3-6.Tablemodelmethodsthatdelegate

callstothewrappedmodel















































publicintgetColumnCount(){



returndelegatedModel.getColumnCount();

}

publicStringgetColumnName(intindex){



returndelegatedModel.getColumnName(index);

}

publicintgetRowCount(){



returndelegatedModel.getRowCount();

}

privateintgetDelegatedRow(introw){



returnsortedIndicies[row];

}

publicObjectgetValueAt(introwIndex,intcolumnIndex



returndelegatedModel.getValueAt(getDelegatedR









columnIndex);

}

publicbooleanisCellEditable(introwIndex,intcolumn



returndelegatedModel.isCellEditable(rowIndex,

}

publicvoidsetValueAt(ObjectaValue,introwIndex,in



delegatedModel.setValueAt(aValue,rowIndex,co

}



Buthowdothecontentsgetsorted?Anyclassthatimplements

ComparablecanbesortedbyCollections.sort()oroneofthe

Arrays.sort()methods,andthusdoesn'trequireanyspecial

handling.However,youprobablywanttohandlesortingany

arbitraryclass,whichrequiresworkingwithcustom

Comparatorswhatthecomparatorsarrayisfor.In

setComparatorForColumn(),yourange-checkthesizeofthearray,

andthencachethepassedComparatorintothearrayindexthat



correspondstothecolumn.Forexample,setComparatorForColumn

(myComparator,2)shouldsetcomparators[2]tomyComparator.

Thiscachesthecomparators,butonlyoneisusedforsortingat

anygiventime.InsetSortColumn(),youcachetheindexofthe

sortcolumn,butthenyouneedtopullupthecorresponding

Comparator.Setthecomparatortheonethatwillbeusedtoperform

thesorttonull,andthencheckthecomparatorslisttoseeif

thereisaComparatoratthegivenindex.Ifso,itwillbecomethe

newcomparator.

Now,you'rereadytohandlethesorting.Whenyouneedto

sort,eitherbecausethesortindexhaschangedorbecausethe

underlyingmodelhaschanged,youcalltheresort()method,

showninExample3-7.



Example3-7.Resortingbasedonthecurrent

comparator



















protectedvoidresort(){



//doessortedIndiciesneedtogroworshrink?



if(sortedIndicies.length!=delegatedModel.get





sortedIndicies=newint[delegatedMode



}



//buildupalistofSortingDelegates



ArrayListsortMe=newArrayList();



for(inti=0;i
































SortingDelegatesd=

newSortingDelegate(delegatedModel.getValueAt(



sortMe.add(sd);

}

//nowsorthimwiththeSortingDelegateCompara

SortingDelegateComparatorsdc=















newSortingDelegateComparator(comparat











Collections.sort(sortMe,sdc);







































//fillsortedIndiciesarray

//index->valuerepresentsmappingfromorigi

//rowtosortedrow

for(inti=0;i














}



//firechangeevent

fireAllChanged();





sortedIndicies[i]=

((SortingDelegate)sortMe.get(i)).row;

}



ThisstartsbyresettingthesizeofthesortedIndiciesarray,which

willbewrongifthenumberofrowsinthedelegatedModelhas

changed.Next,buildupanarraylistofSortingDelegates,aninner

classcontainingavaluefromthedelegatedModel(inthecolumnto

besorted)andamappedrownumber.Thisclassisshownin

Example3-8.



Example3-8.Innerclasstomapsortableobjects

totheirpositioninthecurrentsort

















publicclassSortingDelegateextendsObject{



publicObjectvalue;publicintrow;



publicSortingDelegate(Objectv,intr){





value=v;





row=r;



}

}



ThiscanbesortedbytheSortingDelegateComparator,anotherinner

classthatmapsthecompare()callthatistheheartofJava

Collections-basedsorting(showninExample3-9).Ittakesa

Comparator(namelythesortingcolumn'sComparator,ifany)andon

eachcompare(),itlookstoseeifthatComparatorisnull;ifnot,it

usesComparator.compare()todothesortingcomparison.Inthis

case,objectsshouldbeComparable,whichmeansthesortercan

useComparable.compareTo()toapply"naturalordering"(intuitive

numericorderingforallnumbertypes,ASCIIorderingfor

strings,etc.).Itthrowsanexceptionifthere'sneithera

ComparatortousenorComparablevalues.



Example3-9.Comparatorfordelegatedsorting















classSortingDelegateComparatorextendsObjectimplemen



Comparatorcomp;



publicSortingDelegateComparator(Comparatorc)





comp=c;



}



publicintcompare(Objecto1,Objecto2){



























































}



returncomp.compare(v1,v2);



elseif(v1instanceofComparable)

return((Comparable)v1).compareTo(v2);



else

thrownewIllegalArgumentException("Can'tcomp













}



Objectv1=((SortingDelegate)o1).value

Objectv2=((SortingDelegate)o2).value

if(comp!=null)



WiththelistofSortingDelegatesnowsorted,youcanwalkthelist

andpullouttherowfieldofeachobject,puttingitinthe

sortedIndiciesarray.Thearrayisagainreadytomapallthe

methodcallsthatrefertorows.Youneedtofireaneventtotell

thesortingmodel'slistenerspresumablyjusttheJTablethat

contentshaveupdated.Sincetheresortcouldaffectnone,

some,oralloftherows,fireoffaneventsayingthewholetable

hasupdated.

Thefinalthingtodealwithistheeventsyougetfromthe

wrappedmodel.Thesecanbedeletes,inserts,orupdatesinall

cases,thisimplementationcallsforatotalresortandfiresoff

the"everythingchanged"event.

Atestclassforthismodelneedstoexercisethesortingand

updatingcausedbothbychangingthesortcriteriaandby

changingtheunderlyingmodel.Also,totestthecustom

Comparatorstuff,itneedstohaveatleastonecolumnwhose

contentsaren'tComparableandthusneedaComparator.

TestSortableTableModelprovidesthesewithasimplethree-column



tablewithcannedcontentandbuttonstoresortbyeachof

thosecolumns.Afourthbuttonaddsanotherrowofdata.The

thirdcolumnisajava.awt.Color,whichgetsitsownsimple

Comparator.ThecodeforthetestclassisshowninExample3-10.



Example3-10.Testingtheself-sorting

TableModel













publicclassTestSortableTableModelextendsJPanel



implementsActionListener{



DefaultTableModelmyModel;



SortableTableModelmySortableModel;



JButtonsort1,sort2,sort3,bonus;























staticObject[]headers={



"Letter","Number","Color"

};

staticObject[][]data={















































};

staticObject[]bonusData={



"D","0",Color.red

};



























































publicTestSortableTableModel(DefaultTableMode



super(newBorderLayout());



myModel=m;mySortableModel=newSort



mySortableModel.setComparatorForColumn



JTabletable=newJTable(mySortableMo



table.setDefaultRenderer(java.awt.Colo



JScrollPanescroller=

newJScrollPane(table,



ScrollPaneConstants.VERTICAL_SCROLLBAR



ScrollPaneConstants.HORIZONTAL_SCROLLB



table.setPreferredScrollableViewportSiz



setLayout(newBorderLayout());



add(scroller,BorderLayout.CENTER);

























































{"A",newInteger(2),Color.gray.darker

{"B",newInteger(3),Color.gray},

{"C",newInteger(1),Color.gray.darke



//addsortbuttons

JPanelbuttonPanel=newJPanel();

sort1=newJButton("Sort1");

buttonPanel.add(sort1);

sort1.addActionListener(this);

sort2=newJButton("Sort2");

buttonPanel.add(sort2);

sort2.addActionListener(this);



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Hack 23. Let Your JTables Do the Sorting

Tải bản đầy đủ ngay(0 tr)

×