Tải bản đầy đủ - 0 (trang)
Hack 2. Don't Settle for Boring Text Labels

Hack 2. Don't Settle for Boring Text Labels

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

























privateinttracking;

publicRichJLabel(Stringtext,inttracking){



super(text);



this.tracking=tracking;

}























































privateintleft_x,left_y,right_x,right_y;

privateColorleft_color,right_color;

publicvoidsetLeftShadow(intx,inty,Colorc



left_x=x;



left_y=y;



left_color=color;

}

publicvoidsetRightShadow(intx,inty,Color



right_x=x;



right_y=y;



right_color=color;

}



RichJLabelextendsthestandardjavax.swing.JLabelandaddsa



trackingargumenttotheconstructor.Next,itaddstwomethods

fortherightandleftshadow.Thesearecalledshadowsbecause

theywillbedrawnbelowthemaintext,butwhetherthey

actuallylooklikeshadowsdependsonthecolor,aswellasthe

x-andy-offsetspassedintoeachmethod.

Withtheboilerplateoutoftheway,youneedtohandlesizing

issues.TheJLabelautomaticallytellslayoutmanagersits

preferredsizebasedonthefontsize.Whenyouaddcustom

tracking,thissizingwouldbeincorrect,resultinginlabelstoo

smallforthetexttheycontain.Forsmallfontsizesitwon'tbe

noticeable,butwithlargefancytextandcooleffectsandweall

wantcooleffectsitcouldchopoffhalfofaletterormore.



EverySwingcomponentreturnsitsdesiredsizeusingthe

getPreferredSize()method.Byadjustingthereturnedsizetobea

bitbigger,layoutcontrolsusingthiscomponentwillgivethe

labeltheextraroomitneeds:









publicDimensiongetPreferredSize(){



Stringtext=getText();



FontMetricsfm=this.getFontMetrics(getFont())







intw=fm.stringWidth(text);





w+=(text.length()-1)*tracking;





w+=left_x+right_x;

inth=fm.getHeight();





h+=left_y+right_y;









}



returnnewDimension(w,h);



ThisimplementationofgetPreferredSize()calculatesthesize

basedonthefontmetricsofthecurrentlysettext.The

FontMetricsobjectcontainsmethodstogetthewidthandheight

ofthefontforthecurrenttext.Becausethetrackingvariable

addstotheexistingtrackingofthefont,youcanexpandthe

widthbyaddingatrackingwidthbetweeneachletteroneper

letter,exceptthelastletter.Thelinew+=(text.length(

)-1)*trackingdoesjustthat.Theshadowswillbedrawnthesame

sizeasthebasetext,buttheywillbeoffsetbytheleft_xand

right_xvalues,soyouneedtoaddthoseinaswell.Tracking

onlyaffectsthehorizontalspacebetweenletters,soheightcan

becalculatednormallyviathefontmetrics.getHeight()method.



Don'tforgettoaccountforthoseshadowoffsets!



Withthesizinghandled,theonlythingleftisactuallydrawing

thetextonscreen.AswithallSwingcomponents,overridethe

paintComponent()method(andnotpaint())sothatthechild

componentswillbehandledproperly.

Here'sthefirstbitofthepaintComponent()method:













publicvoidpaintComponent(Graphicsg){



((Graphics2D)g).setRenderingHint(





RenderingHints.KEY_TEXT_ANTIALIASING,





RenderingHints.VALUE_TEXT_ANTIALIAS_ON)



char[]chars=getText().toCharArray();











FontMetricsfm=this.getFontMetrics(getFont())















inth=fm.getAscent();

intx=0;



First,paintComponent()turnsonthegraphicsobject'santi-aliasing

hint.BecausetheRichJLabelclasswilltypicallybeusedforlarge

fontsizesthatneedtobeattractive,it'sprobablyasafebet

thatthedeveloperwantssmoothtext.

Next,themethodgrabsthefontandlinemetricsforthecurrent

textinthecurrentfont.Thegraphicsobjectalwaysdrawstext

fromthebottomoftheletter,ratherthanfromthetop,asyou

wouldexpectwitharectangleorline.

**pg#11*Toaccountforthis,youneedtoknowhowfardowna

lettergoes(itsascent),whichisretrievedfromfm.getAscent().



Afont'sascentisnotthesameastheheightofthefont.Theheight

includesthepartoflettersthatextendbelowthebaseline.Mostletters



stopatthebaselinebutsome,likelowercaseysandgsextendfurther

down.Theascentonlyincludesthepartofthelettersabovethe

baseline,whichiswhatyouwant.



Aftersettingupthevariables,youcanstartdrawingeachletter

(thiscodeisstillinthepaintComponent()method):









for(inti=0;i


charch=chars[i];



intw=fm.charWidth(ch)+tracking;















g.setColor(left_color);

g.drawString(""+chars[i],x-left_x,h-left_y);















g.setColor(right_color);

g.drawString(""+chars[i],x+right_x,h+right_y);















g.setColor(getForeground());

g.drawString(""+chars[i],x,h);











}



x+=w;











((Graphics2D)g).setRenderingHint(



RenderingHints.KEY_TEXT_ANTIALIASING,



RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);











}//endpaintComponent()



Thisisasimpleloopthatcalculatesthewidthofeachcharacter,

plusthetracking,thendrawsitthreetimes:firstwiththeleft

offsets,nextwiththerightoffsets,andfinallyinthenormal

position.Attheendoftheloop,youjustincreasextomoveon



tothenextletter.Therenderinghintlineatthebottomreturns

thegraphicsobjecttoitsoriginalanti-aliasingstate.

Withtheclasscompleted,it'stimetotrysomeeffects.This

codewilldrawlarge(140pt)textingraywithablackdrop

shadowandaslight,whitehighlight:





publicstaticvoidmain(String[]args){





RichJLabellabel=newRichJLabel("76",-40);





//dropshadoww/highlight





label.setLeftShadow(1,1,Color.white);





label.setRightShadow(2,3,Color.black);

label.setForeground(Color.gray);





label.setFont(label.getFont().deriveFont(14of))





















}



JFrameframe=newJFrame("RichJLabelhack");

frame.getContentPane().add(label);

frame.pack();

frame.setVisible(true);



Figure1-8showswhatthecodelookslikerunning.



Figure1-8.Dropshadowtext



Ifyouchangetheshadowstobeonlyonepixeloffsetfromtheir

normalpositionandtosharethesamecolor,thenyoucan

createasubtleoutlineeffect.Settingthetrackingto-30pulls

theletterscloseenoughtooverlapforanicelogoeffect(as

seeninFigure1-9):

















RichJLabellabel=newRichJLabel("76",-30);

//subtleoutline

label.setLeftShadow(1,1,Color.white);

label.setRightShadow(1,1,Color.white);

label.setForeground(Color.blue);

label.setFont(label.getFont().deriveFont(140f));



Figure1-9.Outlinedtext



Theshadowoffsetsletyoueffectivelyrearrangethelettersto

createafaded3Deffect(showninFigure1-10):













//3dletters

label.setLeftShadow(5,5,Color.white);

label.setRightShadow(-3,-3,newColor(0xccccff));

label.setForeground(newColor(0x8888ff));

label.setFont(label.getFont().deriveFont(140f));



Figure1-10.3Dfadedletters



Youcouldexpandonthishackbycombiningitwithimagesand

nicegradientsliketheChristmasCountdowncounterinFigure

1-11.Simplegraphicaleffectsliketheonesshowninthe

RichJLabelareeasytocreatewithSwingthankstothepowerof

Java2D,andtheycanreallymakeyourinterfacespop.



Figure1-11.Mildembosseffect



Hack3.FillYourBorderswithPrettyPictures



Swingcomeswithasetofcustomizableborders,but

sometimesyouwantmorethantheyprovide.Thishack

showshowtocreateacompletelyimagebasedborder

thatcanberesized.

Swinghasaprefabricatedborder,calledtheMatteBorder,which

canacceptanimageinitsconstructor.Forsimpletiled

backgrounds,suchasacheckerboardpattern,thisworksfine.

However,ifyouwanttohaveparticularimagesineachcorner,

creatingafullyresizableimageborder,thenyou'llneed

somethingmorepowerful.Fortunately,Swingmakesitvery

easytocreatecustomborderclasses.Theimageborderinthis

hackwillproduceaborderthatlookslikeFigure1-12.



Figure1-12.Animage-basedborder



ThefirststeptoanycustomborderistosubclassAbstractBorder

andimplementthepaintBorder()method.Theclasswilltake

eightimagesintheconstructor,oneforeachcornerandeach

side;allthecodeisshowninExample1-6.



Example1-6.Buildinganimage-basedborder







publicclassImageBorderextendsAbstractBorder{























Imagetop_center,top_left,top_right;

Imageleft_center,right_center;

Imagebottom_center,bottom_left,bottom_right;

Insetsinsets;



















publicImageBorder(Imagetop_left,Imagetop_ce



Imageleft_center,Imageright_center,



Imagebottom_left,Imagebottom_center,



























































}











publicvoidsetInsets(Insetsinsets){







this.insets=insets;





}































































this.top_left=top_left;

this.top_center=top_center;

this.top_right=top_right;

this.left_center=left_center;

this.right_center=right_center;

this.bottom_left=bottom_left;

this.bottom_center=bottom_center;

this.bottom_right=bottom_right;



publicInsetsgetBorderInsets(Component



if(insets!=null){



returninsets;



}else{



returnnewInsets(top_center.ge



left_center.getWidth(null),



bottom_center.getHeight(null),



}

}



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

Hack 2. Don't Settle for Boring Text Labels

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

×