Tải bản đầy đủ - 0 (trang)
Hack 63. Add a Third Dimension to Swing

Hack 63. Add a Third Dimension to Swing

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

Unfortunately,youwon'tbeabletoobtaintheseresultswithout

alittleimagination.Forinstance,takeacloselookatFigure8-8

andnoticethegradientbackgroundofthewindow.Displaying

suchabackgroundisveryeasywithSwingandtheopaque

propertiesofSwingcomponents,asseenintherathersimple

classinExample8-10.



Example8-10.Ademoprogramfor3D

components

publicBooksDemo()

{



super("AmazonPick");











JButtoncover1=UIHelper.createButton("","cover1_smal

JButtoncover2=UIHelper.createButton("","cover2_smal

JButtoncover3=UIHelper.createButton("","cover3_smal































JPanelbuttons=newJPanel();

buttons.add(cover1);

buttons.add(cover2);

buttons.add(cover3);

buttons.setOpaque(false);





}



UIHelper.centerOnScreen(this);



setContentPane(newGradientPanel());

getContentPane().setLayout(newBorderLayout());

getContentPane().add(buttons,BorderLayout.SOUTH);

pack();

setResizable(false);

setDefaultCloseOperation(EXIT_ON_CLOSE);



Thiscodecreatesthreebuttons,eachcontainingapictureofa

bookloadedbytheutilityclassUIHelper,andthenputsthemina

JPanel.Thispanelisitselfaddedtothecontentpaneofthe

window,atthesouthside.WiththehelpofthesetContentPane()

method,thedefaultcontentpaneisreplacedbyanewpanelan

instanceofGradientPanelthatiscapableofdrawinganice

gradient.Tomakesurethegradientremainsvisibleinthe

buttonspanel,youneedtomakethepaneltransparent.This

canbeachievedeasilybycallingsetOpaque(false),whichwill

preventthecomponentinourcase,thepanelfromdrawingits

background,lettingunderlyingcomponentsshinethrough.

Now,wehavetotakeaslightdiversionintoAWTandSwing

vagaries.WithJ2SE,youcanusetwodifferentgraphicaltoolkits

tocreateanapplication:AWTandSwing.Themaindifference

betweenthosetwoisthatAWTwidgetsareheavyweight

whereasSwingwidgetsarelightweight.Thesenamescome

fromtheverynatureofthesecomponents.Whateverplatform



youarerunningyourapplicationon,AWTwidgetsaredrawn

usingtheunderlyingOSnativetoolkit.Swing,onthecontrary,

iscompletelydecoupledfromtheOSandallthepaintingis

donebyJavaitself.Asaresult,AWTwidgetsaretheleast

commondenominatorbetweenthevariousoperatingsystems

supportedbyJava.Thisalsomeansthatadvancedfeatureslike

transparencyarepurefantasywithAWT:Swingletsyoucreate

transparentcomponentsveryeasily,butAWTdoesnot.

ThebadnewsisthatJava3DoffersanAWTcomponentonly,

Canvas3D,todisplaya3Dscene.Soyou'llhavetomixsome

SwingandAWTcode.Hereishowyoucanaddsucha

componentintheSwingUI:



Canvas3Dc3d=newCanvas3D(SimpleUniverse.getPreferredConfigur

c3d.setSize(CANVAS3D_WIDTH,CANVAS3D_HEIGHT);

getContentPane().add(centerPanel,BorderLayout.CENTER);

createScene();



createScene()isresponsibleforbuildingthe3DscenetheCanvas3D



willdisplay.Runningthiscodewillproducearatheruglyresult,

asshowninFigure8-9.



Figure8-9.ACanvas3Dcannotbemade

transparent



Asyoucansee,youendupwithablackbackgroundinthe

Canva3D.Becausetheonlywaytogetridofacomponent's

backgroundistocallsetOpaque(false)whichisdefinedbyJComponent

andthusisn'tavailabletoAWTcomponentsyouarestuckwith

thisuglybackground.Indeed,asalightweightcomponent,the

canvascannotbemadetransparent.Thingsgetevenworse

whenyoutrytoaddamenubartotheapplicationbecauseof

theorderinwhichcomponentsarepainted:lightweightfirst,

heavyweightnext.Figure8-10showsanexampleofwhat

happenswhenapop-upmenuisdrawnbySwing.Becauseitis

alightweightcomponent,itisdrawnbeforeCanvas3D,whenit

shouldbedrawnafterthecanvas.



Figure8-10.Lightweightcomponentsaredrawn

behindheavyweightcomponents



Thankfully,thisnewproblem(it'sallAWT'sfault!)wasso

annoyingthattheSwingteamdecidedtoaddaworkaroundfor

it.Youcansimplyforceallpop-upmenusofyourapplicationsto

becreatedasheavyweightcomponentsinsteadoflightweight

components.Asinglelineofcodeisenoughtofixtheproblem:

JPopupMenu.setDefaultLightWeightPopupEnabled(false);



IfyouinvokethismethodbeforeyoucreatethefirstJMenuor

JPopupMenu,youensureyourmenuswillbedrawnontopof

heavyweightcomponents.So,thistakescareofoneissue,but

youstillneedtodealwiththeblackbackgroundproblem.



8.9.2.FakingTransparency

BecauseyoucannotchangetheopacityoftheCanvas3D,youare

leftwithonlytwopossiblesolutions.Thefirstistogetridof

Swing,gobacktoAWT,andofferacrappyinterfacetothe

users.Becausethisdoesn'tseemliketoogreatanoption,we'll

justhavetofaketransparency.

AJava3Dsceneisrepresentedasagraphinwhicheverynode

isanobjectoragroupofobjects.Acloselookatthepackage

com.sun.j3d.utils.geometryrevealstheexistenceoftheBackground

class,whichyoucanusetochangethebackgroundofthe3D



scene.Forinstance,youcancreateanAlpinescenejustby

addingabackgroundwithaphotooftheAlpsasitstexture.

Therefore,tofaketransparency,youjusthavetousethe

window'scontentpanelastextureforanewBackgroundobject

thatyouthenaddtothescenegraph.ThisishowAmazonPick

createstheJava3Dsceneandaddsaspecialbackground:

publicvoidcreateScene()

{



BranchGroupobjRoot=newBranchGroup();



objRoot.addChild(createBackground());



//createsthewholescene

}



InJava3D,thesceneisaninstanceofBranchGroup.Byaddingthe

BackgroundcreatedbythemethodcreateBackground()asachildof

thescenenode,youcansetthebackgroundofthescene.The

backgrounditselfiscreatedlikethis:



protectedBackgroundcreateBackground()

{



BufferedImageimage;



image=newBufferedImage(c3d.getParent().getWidth(),

c3d.getParent().getHeight(),









BufferedImage.TYPE_INT_RGB);



getContentPane().paint(image.getGraphics());















BufferedImagesubImage;

subImage=newBufferedImage(CANVAS3D_WIDTH,









CANVAS3D_HEIGHT,









BufferedImage.TYPE_INT

Graphics2DsubGraphics=(Graphics2D)subImage.getGraph

subGraphics.drawImage(image,null,-c3d.getX(),-c3d.ge







ImageComponent2DbackImage;

















backImage=newImageComponent2D(ImageComponent2D.FORMA











subImage)

Backgroundbg=newBackground(backImage);

BoundingSpherebounds=newBoundingSphere();

bounds.setRadius(100.0);

bg.setApplicationBounds(bounds);





}



returnbg;



Thetextureiscreatedintwosteps.Thefirstistocreatea

BufferedImagecalledimageonwhichyoupaintthecontentpanelof

thewindow.Noticethatthepicturehasthesamedimensionsas

thecontentpanel.Callingthepaint()methodofthecomponent

youwanttoseethroughtheJava3Dsceneislessefficientthan

takingascreencapturewiththehelpofjava.awt.Robot;however,

itisaloteasierbecauseitworksevenwhentheCanvas3Dhas

alreadybeenaddedtothewindow.Thisallows,forinstance,

changingthetexturewhenthewindowisresizedandthe

gradientchangesduetothenewdimensions.

Oncethecontentpanelhasbeenfullydrawninimage,youmust

clipittoretrievetheexactpartcoveredbytheCanvas3D.Thisis

donewithanotherBufferedImagecalledsubImage.Thisnewpicture

hasthesamedimensionsasthe3Dscene.Thesecondstepis

todrawimageonsubImage(withoutforgettingtochangetheorigin

ofthedrawingwhenyoucalldrawImage()).Whenthetwolast

parametersofthismethodareboth0,theimageisdrawnon

thetargetsurfacewithitstop-leftcorneratthetarget'stop-left

corner.Withthecoordinatesc3d.getX()andc3d.getY(),thepixelof

imagedrawnatthetop-leftcornerofsubImageisthepixelwhere

theCanvas3Dislocatedonscreen.Thisensuresthecodepaints

theexactpartofthecontentpanelthatliesbehindthe3D

scene.



Then,aBackgroundobjectiscreatedwithsubImageasatexture.To

achievethis,youneedtocreateanImageComponent2Dfromthe

BufferedImageanddon'tforgettomakethepixelformats

compatible!SincesubImagehasitspixelsstoredasRGBintegers,

youmustdothesameforImageComponent2D.Aboundingsphereis

finallyattachedtothebackground.Java3Dusesthissphereto

knowwherethebackgroundobjectneedstoberenderedand

whereitshouldnotberendered.Inthiscase,thebackground

willappearwithinasphereofaradiusof100units.Thisvalue

islargeenoughtopreventanyrenderingproblem.Figure8-11

showsthefinalresult,witha"transparent"3Dsceneandno

bugginesswithpop-upmenus.

RomainGuy



Hack64.TurntheSpotlightonSwing



Usersoftengetlostwhenusingapplications,asifthey

wereintotaldarkness.Whydon'tyouturnonaspotlight

toshowthemtheway?

Mostapplicationsinvolveafairamountofdatamanipulation.

Theusercreates,edits,deletes,andmovesarounddataitems.

Whentheamountofdatabecomesimportant,itisvitalforthe

usertobeabletosearchforitemseasily.Yet,searchresult

displaysareoftenirritatinglycomplicated,andtheresultsarea

paintobrowsethrough.Thishackdescribeshowtodrawa

user'sattentiontoonlythepartsoftheUIyouwanthimtolook

at.



Figure8-11.Alltheproblemsprovokedbymixing

Java3DandSwinghavebeensolved



8.10.1.TheMetaphor

Ifyouhaveeverbeentoacomicshow,tothetheatre,ortothe

circus,you'veprobablynoticedhowspotlightsareusedtomove

yourfocustoaparticularlocationonthestage.Asearch

operationcanbecomparedtoatheatrestage,whereactors

havebeenreplacedbysearchresults.Youjustneedtogetthe

usertofocusontherightlocation.

Takealookatanexampleapplication,showninFigure8-12,

whichdisplaysapredefinedsetofbooksandletsyousearchfor

oneormoreofthembyenteringasearchqueryinthetextfield

atthebottomofthewindow.

Sincetheapplicationisjustademo,youcanonlyenteroneof

thefollowingqueries:books,sci-fi,adams,andpratchett.Each

query,whenvalidatedbytheEnterkey,willfindtherelated



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

Hack 63. Add a Third Dimension to Swing

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

×