Tải bản đầy đủ - 0 (trang)
Hack 19. Turn Methods into List Renderers

Hack 19. Turn Methods into List Renderers

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

programmerusingyourgenericrenderertospecifyamethod

usingastring.Thismethodwillbeusedtorenderthe

component.Becauseyouwillbeusingreflection,youdon'tneed

toknowthekindofobjectsinthelist.Aslongasamethodwith

therequestednameexists,youcancallitandgetavalueout.

ThiswillworkevenifsomeoftheobjectsintheJListhave

differenttypes.Butlet'snotgetaheadofourselves.First,you

needabasiccellrenderer,asseeninExample2-21.



Example2-21.Abasiccellrenderer



publicclassGenericListCellRendererextendsDefaultListCellRen

protectedStringmethod;

publicGenericListCellRenderer(Stringmethod){

super();

this.method=method;

}



publicComponentgetListCellRendererComponent(JListlist,O

intindex,booleanisSelected,booleancellHasFocus){



JLabellabel=(JLabel)super.getListCellRendererCompone

list,value,index,isSelected,cellHasFocus);

label.setText("mytext");

returnlabel;

}



Example2-21declaresasubclassofthe

DefaultListCellRendererthestandardimplementationofa

ListCellRenderer.TheGenericListCellRendererclasstakesamethod

stringinitsconstructor.Thisstringisthenameofthemethod

tocallonthelistvalueobjects.

AllListCellRenderershaveagetListCellRendererComponent()method,



whichreturnsacomponenttodotheactualdrawing.Most

implementations(DefaultListCellRendererincluded)useJLabelsas

thedrawingcomponentsbecausetheyarerelativelylightweight

andcanhavebothtextandicons.Thepreviouscodegetsthe

JLabelcomponentfromthesuperclassandsetsthetexttomy

text.OnceaddedtoaJList,thiscodewillbecalledforeach

iteminthelist,meaningtheywillallbedrawnasmytext.This

works,butitisn'tveryuseful.Nowit'stimetoaddsome

reflection:



try{

Methodmeth=value.getClass().getMethod(method,null

if(meth!=null){

Objectretval=meth.invoke(value,null);

label.setText(""+retval);

}

}catch(Exceptionex){

System.out.println("gotanexecption:"+ex);

ex.printStackTrace();

label.setText(""+value);

}

returnlabel;



Thepreviouscodereplacesthelabel.setText()methodinthe

originalrenderer.Itretrievesthespecifiedmethodfromthe

currentlistvalueandstoresitinaMethodobject.Thisobject

representstheabstractmethoditself.Ifyoudidnew

String("text").getClass().getMethod("toString",null),thenyouwould

getanobjectthatrepresentsthetoString()methodonany

string.Onceyouhavethismethod,youcancallitontheactual

objectathand.meth.invoke()willinvokethemethodonthereal

listitem,returningavalueintoretval.BothgetMethod()andinvoke(

)takeanadditionalargument,whichisnullintheprevious

code.Thisargumentisactuallyanarrayrepresentingthe

argumentstothemethodbeingcalled.Forthishacktowork,



youmustassumethatthemethodhasnoarguments,sonullis

used.

Onceyouhavethereturnvalueofthemethodinhand,youcan

callsetText().Isetitto""+retvalbecausethatwillautomatically

handlenullsandcalltoString()onthevalueitself.Thereflection

codecanthrowanexception,soit'sallwrappeduponaTRycatchblock.Ifthereflectionfails,thenitwillsetthetextusing

toString()onthelistitemasabackup,whichiswhatthe

standardrendererwoulddo.



2.8.2.PuttingItAllTogether

Tousethisnewrenderer,youneedtocreateaJListandsetits

CellRendererproperty.Thefollowingcodecreatesaframewith

oneJListinit,createsacustomrendererforthetoString()

method,thenpacksandshowstheframeonscreen.Thelist

containsanarrayofstrings,representingcommonsubatomic

particles:

publicstaticvoidmain(String[]args){

String[]data={"Proton","Neutron","Electron"};

JListlist=newJList(data);

GenericListCellRendererrenderer=

newGenericListCellRenderer("toString");

list.setCellRenderer(renderer);

JFrameframe=newJFrame("CellRendererHack");

frame.getContentPane().add(list);

frame.pack();

frame.setVisible(true);

}



Thegenericrenderercancallanymethodonthelistitem

objectsaslongasthemethodhasnoargumentsanddoesn't

returnvoid.Itwillevenworkwithprimitives.Youcouldcall

hashCode(),whichreturnsanint,likethis:







GenericListCellRendererrenderer=

newGenericListCellRenderer("hashCode");



UsingtoString()onthestringswillbethesameasthedefault

renderer,simplydrawingProton,Neutron,andElectroninthe

list(seeFigure2-12).



Figure2-12.RendererusingthetoString()

method



TheresultingchangewouldlooklikeFigure2-13.



Figure2-13.RendererusingthehashCode()

method



Usingreflectionforcellrenderersisaverypowerfulconcept

becauseyoucanreusepotentiallycomplicatedcodewithvery

littleadditionaleffort.Usingittodisplaystringsisjustatrivial

example.Imagineyouhadabunchofobjectsrepresenting

entriesfromanRSSfeed.Insteadofcreatingacustomrenderer

orwrappingtheentriesinobjectswithacustomtoString()

method,youcouldusetheGenericListCellRendererwithgetTitle()

toautomaticallycallthegetTitle()methodontheentry

objectsnonewsubclassesorextracode.Justasinglestringand

therenderertakescareoftherest.Thatisthepowerof

reflection.



Hack20.CreateaCollections-Aware

JComboBox



You'vemovedonfromVector;yourcomboboxesshould,

too.

JComboBoxisoneofSwing'soldestcomponents.Unfortunately,it



acceptsarraysofobjectsandVectorsonly.NowthatCollections

objectslikeListhavebeenpartoftheJDKforyears,itwouldbe

nicetousethemdirectlyinacomboboxwithoutshuffling

objectsinandoutofarrays.Fortunately,theJComboBoxusesan

MVC(Model-View-Controller)architecture,soyoucansolvethis

problemwithasimpleimplementationofaComboBoxModel.

Tostart,youneedtofigureoutwhatthecustommodelshould

do.Forourpurposes,itneedstoacceptaListintheconstructor

andpreserveanyorderingsupplied.Anotherniftyfeaturewould

beautomaticupdates.IfyouaddordeletevaluestotheList,

thecomboboxshouldupdateitselfautomatically.Example2-22

isagoodstart.



Example2-22.Abasiccomboboxtoacceptlists

publicclassListComboBoxModelimplementsComboBoxModel{



protectedListdata;





publicListComboBoxModel(Listlist){





this.listeners=newArrayList();





this.data=list;





if(list.size()>0){







selected=list.get(0);



























}



}

















publicObjectgetElementAt(intindex){



returndata.get(index);

}

publicintgetSize(){



returndata.size();

}

















}



protectedListlisteners;

publicvoidaddListDataListener(ListDataListenerl){



listeners.add(l);

}

publicvoidremoveListDataListener(ListDataListenerl)



this.listeners.remove(l);

}



protectedObjectselected;

publicvoidsetSelectedItem(Objectitem){



this.selected=item;

}

publicObjectgetSelectedItem(){



returnthis.selected;

}



Thisimplementationisprettymuchwhatyou'dexpect.Each

methodinComboBoxModelisimplemented(alongwithitsparent

interface,ListDataModel).Theconstructorsavesareferenceto

theListandselectsthefirstelementifthereisone.The

selectedItemaccessorworksasexpected,usingtheselected

variable.getElementAt()andgetSize()bothpasstheworkontothe

underlyingList,andtheListDataListenermethodsworkwitha

secondListformanagingthelisteners.Theimportantthingto



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

Hack 19. Turn Methods into List Renderers

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

×