Tải bản đầy đủ - 0 (trang)
Chapter 18.  More Swing Components

Chapter 18.  More Swing Components

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

18.1.TextComponents

Swingofferssophisticatedtextcomponents,fromplain-text

entryboxestoHTMLinterpreters.ForfullcoverageofSwing's

textcapabilities,seeO'Reilly'sJavaSwing.Inthatencyclopedic

book,severalmeatychaptersaredevotedtotext.It'sahuge

subject;we'lljustscratchthesurfacehere.

Let'sbeginbyexaminingthesimplertextcomponents.

JTextFieldisasingle-linetexteditorandJTextAreaisasimple,

multilinetexteditor.BothJTextFieldandJTextAreaderivefromthe

JTextComponentclass,whichprovidesthefunctionalitytheyhavein

common.Thisincludesmethodsforsettingandretrievingthe

displayedtext,specifyingwhetherthetextis"editable"orreadonly,manipulatingthecursorpositionwithinthetext,and

manipulatingtextselections.

Observingchangesintextcomponentsrequiresan

understandingofhowthecomponentsimplementtheModelView-Controller(MVC)architecture.Youmayrecallfromthelast

chapterthatSwingcomponentsimplementatrueMVC

architecture.It'sinthetextcomponentsthatyoufirstgetan

inklingofaclearseparationbetweentheMandVCpartsofthe

MVCarchitecture.Themodelfortextcomponentsisanobject

calledaDocument.WhenyouaddorremovetextfromaJTextField

oraJTextArea,thecorrespondingDocumentischanged.It'sthe

documentitself,notthevisualcomponents,thatgenerates

text-relatedeventswhensomethingchanges.Toreceive

notificationofJTextAreachanges,therefore,youregisterwiththe

underlyingDocument,notwiththeJTextAreacomponentitself:

JTextAreatextArea=newJTextArea();

Documentdoc=textArea.getDocument();

doc.addDocumentListener(someListener);



Asyou'llseeinanupcomingexample,youcaneasilyhavemore

thanonevisualtextcomponentusethesameunderlying

Documentdatamodel.

Inaddition,JTextFieldcomponentsgenerateActionEvents

whenevertheuserpressestheReturnkeywithinthefield.To

gettheseevents,justimplementtheActionListenerinterfaceand

registeryourlistenerusingtheaddActionListener()method.

Thenextsectionscontainacoupleofsimpleapplicationsthat

showyouhowtoworkwithtextareasandfields.



18.1.1.TheTextEntryBoxApplication

Ourfirstexample,TextEntryBox,createsaJTextAreaandtiesittoa

JTextField,asyoucanseeinFigure18-1.



Figure18-1.TheTextEntryBoxapplication



WhentheuserhitsReturnintheJTextField,wereceivean

ActionEventandaddthelinetotheJTextArea'sdisplay.Tryitout.

YoumayhavetoclickyourmouseintheJTextFieldtogiveit

focusbeforetypinginit.Ifyoufillupthedisplaywithlines,you

cantest-drivethescrollbar:



//file:TextEntryBox.java

importjava.awt.*;

importjava.awt.event.*;

importjavax.swing.*;

publicclassTextEntryBox{

publicstaticvoidmain(String[]args){

JFrameframe=newJFrame("TextEntryBox");

finalJTextAreaarea=newJTextArea();

area.setFont(newFont("Serif",Font.BOLD,18));

area.setText("Howdy!\n");

finalJTextFieldfield=newJTextField();



Containercontent=frame.getContentPane();//unnece

content.add(newJScrollPane(area),BorderLayout.CENTER)

content.add(field,BorderLayout.SOUTH);

field.requestFocus();

field.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEventae){

area.append(field.getText()+'\n');

field.setText("");

}

});



frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(200,300);

frame.setVisible(true);

}

}



TextEntryBoxisexceedinglysimple;we'vedoneafewthingsto



makeitmoreinteresting.Wegivethetextareaabiggerfont



usingComponent'ssetFont()method;fontsarediscussedin

Chapter20.Finally,wewanttobenotifiedwhenevertheuser

pressesReturninthetextfield,soweregisterananonymous

innerclassasalistenerforactionevents.

PressingReturnintheJTextFieldgeneratesanactionevent,and

that'swherethefunbegins.Wehandletheeventinthe

actionPerformed()methodofourinnerActionListener

implementation.Then,weusethegetText()andsetText()

methodstomanipulatethetexttheuserhastyped.These

methodscanbeusedforJTextFieldandJTextAreasincethese

componentsarebothderivedfromtheJTextComponentclassand,

therefore,havesomecommonfunctionality.

Theeventhandler,actionPerformed(),callsfield.getText()toread

thetextthattheusertypedintoourJTextField.Itthenaddsthis

texttotheJTextAreabycallingarea.append().Finally,weclearthe

textfieldbycallingthemethodfield.setText(""),preparingitfor

moreinput.

Remember,thetextcomponentsreallyaredistinctfromthe

textdatamodel,theDocument.WhenyoucallsetText(),getText(),

orappend(),thesemethodsareshorthandforoperationsonan

underlyingDocument.

Bydefault,JTextFieldandJTextAreaareeditable;youcantype

andeditinbothtextcomponents.Theycanbechangedto

output-onlyareasbycallingsetEditable(false).Bothtext

componentsalsosupportselections.Aselectionisarangeof

textthatishighlightedforcopying,cutting,orpastinginyour

windowingsystem.Youselecttextbydraggingthemouseover

it;youcanthencut,copy,andpasteitintoothertextwindows

usingthedefaultkeyboardgestures.Onmostsystemsthese

areCtrl-Cforcopy,Ctrl-Vforpaste,andCtrl-Xforcut(onthe

Macit'sCommand-C,Command-V,andCommand-X).Youcan

alsoprogrammaticallymanagetheseoperationsusingthe

JTextComponent'scut(),copy(),andpaste()methods.Youcould,for

example,createapop-upmenuwiththestandardcut,copy,



andpasteoptionsusingthesemethods.Thecurrenttext

selectionisreturnedbygetSelectedText(),andyoucansetthe

selectionusingselectText(),whichtakesanindexrangeor

selectAll().

NoticehowJTextAreafitsneatlyinsideaJScrollPane.Thescroll

panegivesustheexpectedscrollbarsandscrollingbehaviorif

thetextintheJTextAreabecomestoolargefortheavailable

space.



18.1.2.FormattedText

TheJFormattedTextFieldcomponentprovidesexplicitsupportfor

editingcomplexformattedvaluessuchasnumbersanddates.

JFormattedTextFieldactssomewhatlikeaJTextField,exceptthatit

acceptsaformat-specifyingobjectinitsconstructorand

managesacomplexobjecttype(suchasDateorInteger)

tHRoughitssetValue()andgetValue()methods.Thefollowing

exampleshowstheconstructionofasimpleformwithdifferent

typesofformattedfields:

importjava.text.*;

importjavax.swing.*;

importjavax.swing.text.*;

importjava.util.Date;



publicclass

FormattedFields

{

publicstaticvoidmain(String[]args)throwsExcepti

Boxform=Box.createVerticalBox();

form.add(newJLabel("Name:"));

form.add(newJTextField("JoeUser"));

form.add(newJLabel("Birthday:"));

JFormattedTextFieldbirthdayField=



newJFormattedTextField(newSimpleDateFormat("m

birthdayField.setValue(newDate());

form.add(birthdayField);



form.add(newJLabel("Age:"));

form.add(newJFormattedTextField(newInteger(32)));



form.add(newJLabel("HairsonBody:"));

JFormattedTextFieldhairsField

=newJFormattedTextField(newDecimalFormat("#

hairsField.setValue(newInteger(100000));

form.add(hairsField);

form.add(newJLabel("PhoneNumber:"));

JFormattedTextFieldphoneField=

newJFormattedTextField(newMaskFormatter

phoneField.setValue("(314)555-1212");

form.add(phoneField);



JFrameframe=newJFrame("UserInformation");

frame.getContentPane().add(form);

frame.pack();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS

frame.setVisible(true);

}

}



JFormattedTextFieldcanbeconstructedinavarietyofways.You



canuseaplaininstanceofjava.lang.Number(e.g.,Integerand

Float)asaprototypeorsetthelayoutexplicitlyusinga

formattingobjectfromthejava.textpackage:

java.text.NumberFormat,java.text.DateFormat,orthemorearbitrary

java.text.MaskFormatter.TheNumberFormatandDateFormatclassesof

thejava.textpackagearediscussedinChapters10and11.

MaskFormatterallowsyoutoconstructarbitraryphysicallayout



conventions.Inamoment,we'lldiscussinputfilteringand

componentvalidation,whichalsoallowyoutorestrictthekinds

ofcharactersthatcouldfillthefieldsorperformarbitrary

checksonthedata.Finally,weshouldmentionthatinthis

examplewe'veusedaBoxcontainer.ABoxisjustaSwing

containerthatusesaBoxLayout,whichwe'lldiscussmorein

Chapter19.

AfterconstructionyoucansetavalidvalueusingsetValue()and

retrievethelastvalidvaluewithgetValue().Todothis,you'll

havetocastthevaluebacktothecorrecttypebasedonthe

formatyouareusing.Forexample,thisstatementretrievesthe

datefromourbirthdayfield:

Datebday=(Date)birthdayField.getValue();



JFormattedTextFieldvalidatesitstextwhentheuserattemptsto



shiftfocustoanewfield(eitherbyclickingwiththemouse

outsideofthefieldorusingkeyboardnavigation).Bydefault,

JFormattedTextFieldhandlesinvalidinputbysimplyrevertingto

thelastvalidvalue.Ifyouwishtoallowinvalidinputtoremain

inthefieldforfurtherediting,youcansetthe

setFocusLostBehavior()methodwiththevalue

JFormattedTextField.COMMIT(thedefaultisCOMMIT_OR_REVERT).Inany

case,invalidinputdoesnotchangethevaluepropertyretrieved

bygetValue().



18.1.3.FilteringInput

JFormattedTextFielddoesnotknowaboutallformattypesitself;



insteaditusesAbstractFormatterobjectsthatknowabout

particularformattypes.TheAbstractFormatters,inturn,provide

implementationsoftwointerfaces:DocumentFilterand

NavigationFilter.ADocumentFilterattachestoimplementationsof



Documentandallowsyoutointercepteditingcommands,



modifyingthemasyouwish.ANavigationFiltercanbeattached

toJTextComponentstocontrolthemovementofthecursor(asina

mask-formattedfield).Youcanimplementyourown

AbstractFormattersforusewithJFormattedTextField,and,more

generally,youcanusetheDocumentFilterinterfacetocontrolhow

documentsareeditedinanytypeoftextcomponent.For

example,youcouldcreateaDocumentFilterthatmapscharacters

touppercaseorstrangesymbols.DocumentFilterprovidesalowlevel,edit-by-editmeansofcontrollingormappinguserinput.

Wewillshowanexampleofthisnow.Inthefollowingsection,

wediscusshowtoimplementhigher-levelfieldvalidationthat

ensuresthecorrectnessofdataafteritisentered,inthesame

waythattheformattedtextfielddidforusearlier.



18.1.3.1DocumentFilter

Thefollowingexample,DocFilter,appliesadocumentfiltertoa

JTextField.OurDocumentFiltersimplymapsanyinputto

uppercase.Hereisthecode:

importjava.text.*;

importjavax.swing.*;

importjavax.swing.text.*;



publicclassDocFilter

{

publicstaticvoidmain(String[]args)throwsExceptio

{

JTextFieldfield=newJTextField(30);



((AbstractDocument)(field.getDocument())).setDocume

newDocumentFilter()

{

publicvoidinsertString(

FilterBypassfb,intoffset,Stringstring,Att



throwsBadLocationException

{

fb.insertString(offset,string.toUpperCase(

}



publicvoidreplace(

FilterBypassfb,intoffset,intlength,String

AttributeSetattr)throwsBadLocationException

{

fb.replace(offset,length,string.toUpperCa

}

});



JFrameframe=newJFrame("UserInformation");

frame.getContentPane().add(field);

frame.pack();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE

frame.setVisible(true);

}

}



ThemethodsinsertString()andreplace()oftheDocumentFilter

arecalledwhentextisaddedtothedocumentormodified.

Withinthem,wehaveanopportunitytofilterthetextbefore

passingiton.Whenwearereadytoapplythetext,weusethe

FilterBypassreferencetopassitalong.FilterBypasshasthesame

setofmethods,whichapplythechangesdirectlytothe

document.TheDocumentFilterremove()methodcanalsobeused

tointercepteditstothedocumentthatremovecharacters.One

thingtonoteinourexampleisthatnotallDocumentshavea

setDocumentFilter()method.Instead,wehavetocastour

documenttoanAbstractDocument.Onlydocument

implementationsthatextendAbstractDocumentacceptfilters

(unlessyouimplementyourown).Thissadstateofaffairsis

becausethattheDocumentFilterAPIwasaddedinJava1.4,



anditwasdecidedthatchangescouldnotbemadetothe

originalDocumentinterface.



18.1.4.ValidatingData

Low-levelinputfilteringpreventsyoufromdoingsuchthingsas

enteringanumberwhereacharactershouldbe.Inthissection,

we'regoingtotalkabouthigh-levelvalidation,whichaccounts

forthingslikeFebruaryhavingonly28daysoracredit-card

numberbeingforaVisaorMasterCard.Whereascharacter

filteringpreventsyoufromenteringincorrectdata,field

validationhappensafterdatahasbeenentered.Normally,

validationoccurswhentheusertriestochangefocusandleave

thefield,eitherbyclickingthemouseorthroughkeyboard

navigation.Java1.4addedtheInputVerifierAPI,whichallows

youtovalidatethecontentsofacomponentbeforefocusis

transferred.Althoughwearegoingtotalkaboutthisinthe

contextoftextfields,anInputVerifiercanactuallybeattachedto

anyJComponenttovalidateitsstateinthisway.

Thefollowingexamplecreatesapairoftextfields.Thefirst

allowsanyvaluetobeentered,whilethesecondacceptsonly

numbersbetween0and100.Whenbothfieldsarehappy,you

canfreelymovebetweenthem.However,whenyouenteran

invalidvalueinthesecondfieldandtrytoleave,theprogram

justbeepsandselectsthetext.Thefocusremainstrappeduntil

youcorrecttheproblem.

importjavax.swing.*;



publicclassValidator

{

publicstaticvoidmain(String[]args)throwsExcepti

Boxform=Box.createVerticalBox();

form.add(newJLabel("AnyValue"));

form.add(newJTextField("5000"));



form.add(newJLabel("Only0-100"));

JTextFieldrangeField=newJTextField("50");

rangeField.setInputVerifier(newInputVerifier()

publicbooleanverify(JComponentcomp){

JTextFieldfield=(JTextField)comp;

booleanpassed=false;

try{

intn=Integer.parseInt(field.getText(

passed=(0<=n&&n<=100);

}catch(NumberFormatExceptione){}

if(!passed){

comp.getToolkit().beep();

field.selectAll();

}

returnpassed;

}

});

form.add(rangeField);



JFrameframe=newJFrame("UserInformation");

frame.getContentPane().add(form);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS

frame.pack();

frame.setVisible(true);

}

}



Wehavecreatedananonymousinnerclassextending

InputVerifierwiththiscode.TheAPIisverysimple;atvalidation

timeourverify()methodiscalled,andwearepasseda

referencetothecomponentneedingchecking.Herewecastto

thecorrecttype(weknowwhatweareverifying,ofcourse)and

parsethenumber.Ifitisoutofrange,webeepandselectthe

text.WethenreturnTRueorfalseindicatingwhetherthevalue



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

Chapter 18.  More Swing Components

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

×