Tải bản đầy đủ - 0 (trang)
Hack 8. Animate Transitions Between Tabs

Hack 8. Animate Transitions Between Tabs

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

Example1-16.Askeletonforthetransition

manager



publicclassTransitionTabbedPaneextendsJTabbedPane





implementsChangeListener,Runnable{





protectedintanimation_length=20;

publicTransitionTabbedPane(){







super();







this.addChangeListener(this);





































}

publicintgetAnimationLength(){



returnthis.animation_length;

}

publicvoidsetAnimationLength(intlength){



this.animation_length=length;

}



transitionTabbedPaneextendsthestandardJTabbedPaneandalso



implementsChangeListenerandRunnable.ChangeListenerallowsyou

tolearnwhentheuserhasswitchedbetweentabs.Sincethe

eventispropagatedbeforethenewtabispainted,insertingthe

animationisveryeasy.Runnableisusedfortheanimationthread

itself.



Youcouldhavesplitthethreadintoaseparateclass,butIthinkthat

keepingallofthecodetogethermakesthesystemmoreencapsulated

andeasiertomaintain.



TRansitionTabbedPaneaddsonenewproperty,theanimationlength.



Thisdefinesthenumberofstepsusedforthetransition,andit

canbesetbythesubclassorexternalcode.



1.9.2.SchedulingtheAnimation

SincethepanewasaddedasaChangeListenertoitself,the

stateChanged()methodwillbecalledwhenevertheuserswitches

tabs.Thisisthebestplacetostarttheanimationthread.Once

started,thethreadwillcapturetheprevioustabintoabuffer,

loopthroughtheanimation,andcontroltherepaintspeed:











//threadingcode

publicvoidstateChanged(ChangeEventevt){



newThread(this).start();

}











protectedintstep;

protectedBufferedImagebuf=null;

protectedintprevious_tab=-1;









publicvoidrun(){



step=0;













//savetheprevioustab

if(previous_tab!=-1){



Componentcomp=this.getComponentAt(previous_t



buf=newBufferedImage(comp.getWidth(),



















}





comp.getHeight(),



BufferedImage.TYPE_4BYTE_ABGR);

comp.paint(buf.getGraphics());



Noticethattherun()methodgrabstheprevioustabcomponent



onlywhentheprevious_tabindexisn't-1.Thecomponentwill

alwayshaveavalidvalue,exceptforthefirsttimethepaneis

shownonscreen,butthat'sOKbecausetheuserwon'thave

reallyswitchedfromanythinganyway.Ifthereisaprevious

tab,thenthecodegrabsthecomponentandpaintsitintoa

bufferimage.



It'simportanttonotethatthisisnotthread-safebecausethecodeis

beingexecutedonacustomthread,nottheSwingthread.However,

sincethetabisabouttobehiddenanywayand,infact,thenextreal

paint()callwillonlydrawthenewtabyoushouldn'thaveanyproblems.

Anychangesintroducedbythisextrapaint()callwon'tshowupon

screen.



Withthepreviouscomponentsafelysavedaway,youcannow

loopthroughtheanimation:











for(inti=0;i
step=i;

repaint();

try{











}





Thread.currentThread().sleep(100);

}catch(Exceptionex){



p("ex:"+ex);

}











step=-1;

previous_tab=this.getSelectedIndex();

repaint();



Thiscodeshowsabasicanimationloopfrom1toN,witha100-



milliseconddurationforeachframe.



Amoresophisticatedversionofthecodecouldhavedynamicframe

ratestoadjustforsystemspeed.



Oncethetransitionfinishes,theanimationstepissetbackto

-1,theprevioustabisstored,andthescreenisrepaintedone

lasttime,withoutthetransitioneffects.



1.9.3.DrawingtheAnimation

TheTRansitionTabbedPaneisnowsetupwiththeproperresources

andrepaints,butitstillisn'tdrawingtheanimation.Because

theanimationisgoingtopartiallyorcompletelyobscurethe

tabsunderneath,thebestplacetodrawisrightafterthe

childrenarepainted:







publicvoidpaintChildren(Graphicsg){



super.paintChildren(g);



























}











publicvoidpaintTransition(Graphics2Dg2,intstep,



Rectanglesize,Imageprev){

}



if(step!=-1){



Rectanglesize=this.getComponentAt(0)



Graphics2Dg2=(Graphics2D)g;



paintTransition(g2,step,size,buf);

}



ThiscodeputsallofthecustomdrawingintothepaintTransition(

)method,currentlyempty.Itwillonlybecalledifstepisn't-1,

meaningduringatransitionanimation.ThepaintTransition()

methodprovidesthedrawingcanvas,thecurrentanimation

step,thesizeandpositionofthecontentarea(excludingthe

tabsthemselves),andtheimagebufferthatstorestheprevious

tab'scontent.Byputtingallofthisinasinglemethod,

subclassescanbuildtheirownanimationsveryeasily.Example

1-17isasimpletransitionwithawhiterectanglethatgrowsout

ofthecenter,fillingthescreen,thenshrinkingagaintoreveal

thenewtabcontent.



Example1-17.Settingupananimatedtransition









publicclassInOutPaneextendsTransitionTabbedPane{



publicvoidpaintTransition(Graphics2Dg2,int





Rectanglesize,Imageprev){







intlength=getAnimationLength();





inthalf=length/2;





doublescale=size.getHeight()/length;





intoffset=0;





//calculatethefadeoutpart





if(state>=0&&state
//drawthesavedversionoftheoldtabcomponent





if(prev!=null){







g2.drawImage(prev,(int)size.getX(),(int





}





offset=(int)((10-state)*scale);



}



//calculatethefadeinpart



if(state>=half&&state




g2.setColor(Color.white);





offset=(int)((state-10)*scale);





}











//dothedrawing

g2.setColor(Color.white);

Rectanglearea=newRectangle((int)(size.getX()+offset























}



g2.fill(area);

}



(int)(size.getY()+offset),

(int)(size.getWidth()-offset*2),

(int)(size.getHeight()-offset*2));



InOutPaneimplementsonlythepaintTransition()method,leaving



allofthehardertaskstotheparentclass.First,itdetermines

howlongtheanimationwillbe,andthenitcalculatesanoffset

togrowandshrinkthewhiterectangle.Ifthedrawingprocess

iscurrentlyinthefirsthalfoftheanimation(step
drawstheprevioustabbelowtherectangle,creatingtheillusion

thatoldtabcontentisstillreallyonscreenwiththerectangle

growingaboveit.Forthesecondhalfoftheanimation,itjust

drawstherectangle,lettingtherealtab(thenewone)shine

throughastherectangleshrinks.



1.9.4.PuttingItAllTogether

BecausetransitionTabbedPaneisjustaJTabbedPanesubclass,itcan

beusedwherevertheoriginalwouldbe.Example1-18creates

aframewithtwotabs,eachcontainingabutton.Therunning

programlookslikeFigure1-23.Asyouswitchbetweenthe

tabs,youwillseeananimationlikethatshowninFigure1-24.



Example1-18.Testingouttabbedanimation



transitions





publicclassTabFadeTest{





publicstaticvoidmain(String[]args){







JFrameframe=newJFrame("FadeTabs");

JTabbedPanetab=newInOutPane();







tab.addTab("t1",newJButton("TestButto







tab.addTab("t2",newJButton("TestButto

























frame.getContentPane().add(tab);

frame.pack();

frame.show();

















}



}



Figure1-23.Twotabs,beforetransitioneffect

begins



Figure1-24.Tabtransitionatmid-point



1.9.5.AnotherExample

BecauseTRansitionTabbedPanemakesitsoeasytobuildnew

animations,IthoughtI'daddanotherone.Thisistheold

venetianblindseffect,whereverticalbarscovertheoldscreen

anduncoverthenewone;Example1-19putsittogether.



Example1-19.Creatingavenetianblindseffect













publicclassVenetianPaneextendsTransitionTabbedPane



publicvoidpaintTransition(Graphics2Dg2,int







Rectanglesize,Imageprev){





intlength=getAnimationLength();





inthalf=length/2;





















//createablind

Rectangleblind=newRectangle();

































//calculatethefadeoutpart

if(step>=0&&step


//drawthesavedversionofth



if(prev!=null){



















g2.drawImage(prev,(int)size.get



































































}

//calculatethegrowingblind

blind=newRectangle(

(int)size.getX(),

(int)size.getY(),

step,

(int)size.getHeight());







































}

//calculatethefadeinpart

if(step>=half&&step


//calculatetheshrinkingblin



blind=newRectangle(











































(int)size.getX(),

(int)size.getY(),

length-step,

(int)size.getHeight());























}



blind.translate(step-half,0);







































//drawtheblinds

for(inti=0;i


g2.setColor(Color.white);



g2.fill(blind);



blind.translate(half,0);























}





}



}



JustlikeInOutPane,VenetianPaneselectivelydrawstheoldtaband

thencalculatestheplacementofanimatedrectangles.Inthis

case,thereisablindrectanglethatspanstheentirescreen



fromtoptobottom,buthasthewidthofthecurrentstep.Asa

resultofthestepgrowing,thisrectanglegetsbiggerwitheach

frame.Forthesecondhalfoftheanimation,itshrinksand

movestotheright,makingitappeartofadeintonothing.Once

theblindiscalculated,VenetianPanedrawstheblindmultiple

timestocovertheentiretabcontentarea,creatingtheeffect

seeninFigure1-25.



Figure1-25.Tabtransitionwithavenetianblinds

effect



Thishackisquiteextensible.WiththepowerofJava2Dyou

couldaddtranslucency,blurs,OSX-likegenieeffects,or

anythingelseyoucandreamup.Asafutureenhancement,you

couldincludemoreanimationsettingstocontroltheframerate

andtransitiontime.Ifyoudocreatemore,pleasepostthemon

theWebforotherstoshare.



Hack9.BlurDisabledComponents



Thishackexplorescreatinghowtoperformablur

transformationonaSwingcomponent.

EverySwingcomponentdrawstothescreenviathe

paintComponent()method.Thisistrueevenforcomponentsthat

offloadtheactualdrawingtoLookandFeelUIobjects.Because

alldrawinggoesthroughthepaintComponent()methodatsome

point,thispointiswhereyoucandosomeinterestingthingsby

manipulatingthegraphicsobjectduringthepaintprocess.

SwingcomponentsdrawtotheGraphicsobjectpassedinthrough

thepaintComponent()method.Thismeansthatifyoureplacethe

Graphicsobjectwithacustomversion,youcancapturea

component'sdrawingintoabitmapinsteadofgoingstraightto

thescreen.

Blurringisapixel-leveloperation,meaningtheactualblurringis

donepixel-by-pixelinabitmap.Bydrawingthecomponenttoa

bitmap,blurringthatbitmap,andthendrawingthebitmapin

theplaceofthecomponent,youcaneffectivelyhaveablurred

componentwithoutdisturbingtherestoftheSwingpainting

routines.Theparticularimplementationinthishackusesa

blurredeffecttoreplacethenormalgrayingofacomponent

whenitisdisabled.

Thefirststepistocapturethebuttonintoabitmap,asshown

inExample1-20.



Example1-20.Creatingablurrablebutton



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

Hack 8. Animate Transitions Between Tabs

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

×