學(xué)習(xí)qt高級(jí)編程3 3基本原理_第1頁(yè)
學(xué)習(xí)qt高級(jí)編程3 3基本原理_第2頁(yè)
學(xué)習(xí)qt高級(jí)編程3 3基本原理_第3頁(yè)
學(xué)習(xí)qt高級(jí)編程3 3基本原理_第4頁(yè)
學(xué)習(xí)qt高級(jí)編程3 3基本原理_第5頁(yè)
已閱讀5頁(yè),還剩115頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第一章自定義控 直接繼承 第二章SIGNAL和SLOT機(jī) 介 小 第三章QT的介 小 第四章多進(jìn)程通 介 QCOP協(xié) FIFO機(jī) 第五章QT的繪 介 小 第六章QT多線程編程(環(huán)境中掉不講 介 小 第七章輸入法和插 概 InputMethods簡(jiǎn) 第八章網(wǎng)絡(luò)編 介 小 第九章 簡(jiǎn) QtSAX2 QtDom 1HexSpinBox#ifndefHEXSPINBOX_H#defineHEXSPINBOX_HclassHexSpinBox:public{HexSpinBox(QWidget*parent,constchar*name=0);QStringmapValueToText(intvalue);intmapTextToValue(bool*ok);TheHexSpinBoxinheritsmostofitsfunctionalityfromQSpinBox.ItprovidesatypicalconstructorandreimplementstwovirtualfunctionsfromQSpinBox.Sincetheclassdoesn'tdefineitsownsignalsandslots,itdoesn'tneedtheQ_#includeHexSpinBox::HexSpinBox(QWidget*parent,constchar:QSpinBox(parent,{setValidator(newQRegExpValidator(regExp,this));setRange(0,255);}Theusercanmodifyaspinbox'scurrentvalueeitherbyclickingitsupanddownarrowsorbytyavalueintothespinbox'slineeditor.Inthelattercase,wewanttorestricttheuser'sinputtolegitimatehexadecimalnumbers.Toachievethis,weuseaQRegExpValidatorthatacceptsoneormorecharactersfromtheranges'0'to'9','A'to'F',and'a'to'f'.Wealsosetthedefaultrangetobe0to255(0x00to0xFF),whichismoreappropriateforahexadecimalspinboxthanQSpinBox'sdefaultof0to99.{returnQString::number(value,}ThemapValueToText()functionconvertsanintegervaluetoastring.QSpinBoxcallsittoupdatetheeditorpartofthespinboxwhentheuserpressesthespinbox'supordownarrows.WeusethestaticfunctionQString::number()withasecondargumentof16toconvertthevaluetolower-casehexadecimal,andcallQString::upper()ontheresulttomakeituppercase.{returntext().toInt(ok,}ThemapTextToValue()functionperformsthereverseconversion,fromastringtopartofthespinboxandpressesEnter.WeusetheQString::toInt()functiontoattempttoconvertthecurrenttext(returnedbyQSpinBox::text())toanintegervalue,againusingbase16.Iftheconversionissuccessful,toInt()sets*oktotrue;otherwise,itsetsitfalse.ThisbehaviorhappenstobeexactlywhatQSpinBoxWehavenowfinishedthehexadecimalspinbox.CustomizingotherQtwidgetsfollowsthesamepattern:PickasuitableQtwidget,subclassit,andreimplementsomevirtualfunctionstochangeitsbehavior.ThistechniqueiscommoninQtbuilt-inQtwidgetsorothercustomwidgetssuchasHexSpinBox.CustomwidgetsthatarebuiltbycomposingexistingwidgetscanusuallybedevelopedinQtDesigner:Createanewformusingthe"Widget"temAddthenecessarywidgetstotheform,thenlaythemSetupthesignalsandslotsconnectionsandaddanynecessarycode(eitherina.ui.hfileorinasubclass)toprovidethedesiredbehavior.Naturally,thiscanalsobedoneentirelyincode.Whicheverapproachistaken,theresultingclassinheritsdirectlyfromQWidget.Ifthewidgethasnosignalsandslotsofitsownanddoesn'treimplementanyvirtualfunctions,itisevenpossibletosimplyassemblethewidgetbyaggregatingexistingwidgetswithoutasubclass.That'stheapproachweusedinChapter1tocreatetheAgeapplication,withaQHBox,aQSpinBox,andaQSlider.Evenso,wecouldjustaseasilyhavesubclassedQHBoxandcreatedtheQSpinBoxandQSliderinthesubclass'sconstructor.WhennoneofQt'swidgetsaresuitableforthetaskathand,andwhenthere'snowaytocombineoradaptexistingwidgetstoobtainthedesiredresult,wecanstillcreatethewidgetwewant.ThisisachievedbysubclassingQWidgetandreimplementingafeweventhandlerstopaintthewidgetandtorespondtomouseclicks.Thisapproachgivesuscomplete domtodefineandcontrolboththeappearanceandthebehaviorofourwidget.Qt'sbuilt-inwidgets,likeQLabel,QPushButton,andQTable,areimplementedthisway.Iftheydidn'texistinQt,itwouldstillbepossibletocreatethemourselvesusingthepublicfunctionsprovidedbyQWidgetinatotallytform-independentmanner.IconEditorwidgetshowninFigure5.2.TheIconEditorisawidgetthatcouldbeusedinaniconeditingprogram.2Let'sbeginbyreviewingtheheader#include<qimage.h>classIconEditor:publicQ_PROPERTY(QColorpenColorREADpenColorWRITEsetPenColor)Q_PROPERTY(QImageiconImageREADiconImageWRITEsetIconImage)Q_PROPERTY(intzoomFactorREADzoomFactorWRITEsetZoomFactor)IconEditor(QWidget*parent=0,constchar*name=0);voidsetPenColor(constQColor&newColor);QColorpenColor()const{returncurColor;}voidsetZoomFactor(intnewZoom);intzoomFactor()const{returnzoom;}voidsetIconImage(constQImage&newImage);constQImage&iconImage()const{returnimage;}QSizesizeHint()const;TheIconEditorclassusestheQ_PROPERTY()macrotodeclarethreecustompenColor,iconImage,andzoomFactor.Eachpropertyhasatype,a"read"function,anda"write"function.Forexample,thepenColorpropertyisoftypeQColorandcanbereadandwrittenusingthepenColor()andsetPenColor()functions.WhenwemakeuseofthewidgetinQtDesigner,custompropertiesappearinQtDesigner'spropertyeditorbelowthepropertiesinheritedfromQWidget.PropertiesmaybeofanytypesupportedbyQVariant.TheQ_OBJECTmacroisnecessaryforclassesthatdefineproperties.voidmousePressEvent(QMouseEvent*event);voidmouseMoveEvent(QMouseEvent*event);voidpaintEvent(QPaintEvent*event);voiddrawImagePixel(QPainter*painter,inti,intj);voidsetImagePixel(constQPoint&pos,boolopaque);QColorcurColor;intzoom;IconEditorreimplementsthreeprotectedfunctionsfromQWidgetandhasafewprivatefunctionsandvariables.Thethreeprivatevariablesholdthevaluesofthethreeproperties.Theimplementationfilebeginswith#includedirectivesandtheIconEditor's#include<qpainter.h>IconEditor::IconEditor(QWidget*parent,constchar:QWidget(parent,name,{curColor=black;zoom=image.create(16,16,image.fill(qRgba(0,0,0,0));}TheconstructorhassomesubtleaspectssuchasthesetSize()callandWStaticContentsflag.WewilldiscussthemThezoomfactorissetto8,meaningthateachpixelintheiconwillberenderedasintheQtclass(QObject'sbaseclass).TheicondataisstoredintheimagemembervariableandcanbeaccessedthroughthesetIconImage()andiconImage()functions.AniconeditorprogramwouldtypicallycallsetIconImage()whentheuseropensaniconfileandiconImage()toretrievetheiconwhentheuserwantstosaveit.TheimagevariableisoftypeQImage.Weinitializeitto16x16pixelsand32-bitdepth,cleartheimagedata,andenablethealphabuffer.TheQImageclassstoresanimageinahardware-independentfashion.Itcanbesettousea1-bit,8-bit,or32-bitdepth.Animagewith32-bitdepthuses8bitsforeachofthered,green,andbluecomponentsofapixel.Theremaining8bitsstorethepixel'salphacomponent—thatis,itsopacity.Forexample,apureredcolor'sred,green,blue,andalphacomponentshavethevalues255,0,0,and255.InQt,thiscolorcanbespecifiedasQRgbred=qRgba(255,0,0,orQRgbred=qRgb(255,0,QRgbissimplyatypedefforunsignedint,andqRgb()andqRgba()areinlinefunctionsthatcombinetheirargumentsintoone32-bitintegervalue.ItisalsopossibletowriteQRgbred=component.IntheIconEditorconstructor,wefilltheQImagewithatransparentcolorbyusing0asthealphacomponent.Qtprovidestwotypesforstoringcolors:QRgbandQColor.WhileQRgbisonlyatypedefusedinQImagetostore32-bitpixeldata,QColorisaclasswithmanyusefulfunctionsandiswidelyusedinQttostorecolors.IntheIconEditorwidget,weonlyuseQRgbwhendealingwiththeQImage;weuseQColorforeverythingelse,includingthepenColorproperty.QSizeIconEditor::sizeHint(){QSizesize=zoom*image.size();if(zoom>=3)size+=QSize(1,1);returnsize;}ThesizeHint()functionisreimplementedfromQWidgetandreturnstheidealsizeofawidget.Here,wetaketheimagesizemultipliedbythezoomfactor,withoneextrapixelineachdirectionto modateagridifthezoomfactoris3ormore.(Wedon'tshowagridifthezoomfactoris2or1,becausethegridwouldhardlyleaveanyroomfortheicon'spixels.)Awidget'ssizehintismostlyusefulinconjunctionwithlayouts.Qt'slayoutmanagerstryasmuchaspossibletorespectawidget'ssizehintwhentheylayoutaform'schildwidgets.ForIconEditortobeagoodlayoutcitizen,itmustreportacrediblesizehint.Inadditiontothesizehint,widgetshaveasizethatlsthelayoutsystemwhethertheyliketobestretchedandshrunk.BycallingsetSize()intheconstructorwithQSize::Minimumashorizontalandverticalpolicies,welanylayoutmanagerthatisresponsibleforthiswidgetthatthewidget'ssizehintisreallyitsminimumsize.Inotherwords,thewidgetcanbestretchedifrequired,butitshouldnevershrinkbelowthesizehint.ThiscanbeoverriddeninQtDesignerbysettingthewidget'ssizeproperty.ThemeaningofthevarioussizepoliciesisexinedinChapter6(LayoutManagement).voidIconEditor::setPenColor(constQColor{curColor=}ThesetPenColor()functionsetsthecurrentpencolor.Thecolorwillbeusedfornewlydrawnpixels.voidIconEditor::setIconImage(constQImage{if(newImage!=image)image=newImage.convertDepth(32);}}ThesetIconImage()functionsetstheimagetoedit.WecallconvertDepth()tomaketheimage32-bitifitisn'talready.Elsewhereinthecode,wewillassumethattheimagedataisstoredas32-bitQRgbvalues.Wealsocalldetach()totakeadeepcopyofthedatastoredintheimage.ThisisnecessarybecausetheimagedatamightbestoredinROM.QImagetriestosavetimeandmemorybycopyingtheimagedataonlywhenexplicitlyrequestedtodoso.ThisoptimizationiscalledexplicitsharingandisdiscussedwithQMemArray<T>inthe"Pointer-BasedContainers"sectionofChapter11.Aftersettingtheimagevariable,wecallQWidget::update()to ofthewidgetusingthenewimage.Next,wecallQWidget::updateGeometry()tolanylayoutthatcontainsthewidgetthatthewidget'ssizehinthaschanged.Thelayoutwillthenautomaticallyadapttothenewsize{if(newZoom<1)newZoom=1;if(newZoom!={zoom=newZoom;}}ThesetZoomFactor()functionsetsthezoomfactorfortheimage.Topreventdivisionbyzerolater,wecorrectanyvaluebelow1.Again,wecallupdate()andupdateGeometry()torepaintthewidgetandtonotifyanymanaginglayoutaboutthesizehintchange.ThepenColor(),iconImage(),andzoomFactor()functionsareimplementedasinlinefunctionsintheheaderfile.WewillnowreviewthecodeforthepaintEvent()function.ThisfunctionIconEditor'smostimportantfunction.Itiscalledwheneverthewidgetrepainting.ThedefaultimplementationinQWidgetdoesnothing,leavingthewidgetJustlikecontext Event()andcloseEvent(),whichwemetinChapter3,correspondstoadifferenttypeofevent.Chapter7coverseventprocessinginTherearemanysituationswhenapainteventisgeneratedandpaintEvent()isWhenawidgetisshownforthefirsttime,thesystemautomaticallygeneratesapainteventtothewidgettopaintitself.Whenawidgetisresized,thesystemautomaticallygeneratesapaintIfthewidgetisobscuredbyanotherwindowandthenrevealedagain,apainteventisgeneratedfortheareathatwashidden(unlessthewindowsystemstoredthearea).Wecan apainteventbycallingQWidget::update()QWidget::repaint().Thedifferencebetweenthesetwofunctionsisthatrepaint()sanimmediaterepaint,whereasupdate()simplyschedulesapainteventforwhenQtnextprocessesevents.(Bothfunctionsdonothingifthewidgetisn'tonscreen.)Ifupdate()iscalledmultipletimes,Qtcompressestheconsecutivepainteventsintoasinglepainteventtoavoidflicker.InIconEditor,wealwaysuseHere'sthe{if(zoom>=3){for(inti=0;i<=image.width();++i)painter.drawLine(zoom*i,0,zoom*i,zoom*for(intj=0;j<=image.height();++j)painter.drawLine(0,zoom*j,zoom*image.width(),zoom*}for(inti=0;i<image.width();{for(intj=0;j<image.height();++j)drawImagePixel(&painter,i,j);}}WestartbyconstructingaQPainterobjectonthewidget.Ifthezoomfactoris3ormore,wedrawthehorizontalandverticallinesthatformthegridusingtheQPainter::drawLine()function.AcalltoQPainter::drawLine()hasthefollowingpainter.drawLine(x1,y1,x2,where(x1,y1)isthepositionofoneendofthelineand(x2,y2)isthepositionoftheotherend.ThereisalsoanoverloadedversionofthefunctionthattakestwoQPointsinsteadoffourints.Thetop-leftpixelofaQtwidgetislocatedatposition(0,0),andthebottomrightpixelislocatedat(width()–1,height()–1).ThisissimilartotheconventionalCartesiancoordinatesystem,butupsidedown,andmakesalotofsenseinGUIprogramming.ItisperfectlypossibletochangeQPainter'scoordinatesystembyusingtransformations,suchastranslation,scaling,rotation,andshearing.ThisiscoveredinChapter8(2Dand3DGraphics).3QPainterBeforewecalldrawLine()ontheQPainter,wesettheline'scolorusingsetPen().Wecouldhard-codeacolor,likeblackorgray,butabetterapproachistousethewidget'spalette.Everywidgetisequippedwithapalettethatspecifieswhichcolorsshouldbeusedforwhat.Forexample,thereisapaletteentryforthebackgroundcolorofwidgets(usuallylightgray)andoneforthecoloroftextonthatbackground(usuallyblack).Bydefault,awidget'spaletteadoptsthewindowsystem'scolorscheme.ByusingAwidget'spaletteconsistsofthreecolorgroups:active,inactive,anddisabled.Whichcolorgroupshouldbeuseddependsonthewidget'scurrentTheactivecolorgroupisusedforwidgetsinthecurrentlyactiveTheinactivecolorgroupisusedforwidgetsintheotherThedisabledcolorgroupisusedfordisabledwidgetsinanyTheQWidget::palette()functionreturnsthewidget'spaletteasaQPaletteobject.ThecolorgroupsareavailablethroughQPalette'sactive(),inactive(),anddisabled()functions,andareoftypeQColorGroup.Forconvenience,QWidget::colorGroup()returnsthecorrectcolorgroupforthecurrentstateofthewidget,sowerarelyneedtoaccessthepalettedirectly.ThepaintEvent()functionfinishesbydrawingtheimageitself,usingtheIconEditor::drawImagePixel()functiontodraweachoftheicon'spixelsasfilledvoidIconEditor::drawImagePixel(QPainter*painter,inti,int{QColorQRgbrgb=image.pixel(i,j);if(qAlpha(rgb)==0)color=colorGroup().base();if(zoom>=3){painter->fillRect(zoom*i+1,zoom*j+1,zoom-1,zoom-1,color);}elsepainter->fillRect(zoom*i,zoom*j,zoom,zoom,color);}}jparametersarepixelcoordinatesintheQImage—notinthewidget.(Ifthezoomfactoris1,thetwocoordinatesystemscoincideexactly.)Ifthepixelistransparent(itsalphacomponentis0),weusethecurrentcolorgroup's"base"color(typicallywhite)todrawthepixel;otherwise,weusethepixel'scolorintheimage.ThenwecallQPainter::fillRect()todrawafilledsquare.Ifthegridisshown,thesquareisreducedbyonepixelinbothdirectionstoavoidpaintingoverthegrid.4QPainterThecalltoQPainter::fillRect()hasthefollowingpainter->fillRect(x,y,w,h,where(x,y)isthepositionofthetop-leftcorneroftherectangle,wxhisthesizeoftherectangle,andbrushspecifiesthecolortofillwithandthefillpatterntouse.BypassingaQColorasthebrush,weobtainasolidfillpattern.{if(event->button()==LeftButton)elseif(event->button()==RightButton)setImagePixel(event->pos(),false);}Whentheuserpressesamousebutton,thesystemgeneratesa"mousepress"event.ByreimplementingQWidget::mousePressEvent(),wecanrespondtothiseventandsetorcleartheimagepixelunderthemousecursor.Iftheuserpressedtheleftmousebutton,wecalltheprivatefunctionsetImagePixel()withtrueasthesecondargument, lingittosetthepixeltothecurrentpencolor.Iftheuserpressedtherightmousebutton,wealsocallsetImagePixel(),butpassfalsetoclearthepixel.{if(event->state()&LeftButton)setImagePixel(event->pos(),true);elseif(event->state()&RightButton)setImagePixel(event->pos(),false);}onlygeneratedwhentheuserisholdingdownabutton.ItispossibletochangethisbehaviorbycallingQWidget::setMouseTracking(),butwedon'tneedtodosoforthisexample.Justaspressingtheleftorrightmousebuttonsetsorclearsapixel,keeitpressedandhoveringoverapixelisalsoenoughtosetorclearapixel.Sinceit'spossibletoholdmorethanonebuttonpresseddownatatime,thevaluereturnedbyQMouseEvent::state()isabitwiseORofthemousebuttons(andofmodifierkeyslikeShiftandCtrl).Wetestwhetheracertainbuttonispresseddownusingthe&operator,andifitis,wecallsetImagePixel().voidIconEditor::setImagePixel(constQPoint&pos,bool{inti=pos.x()/zoom;intj=pos.y()/if(image.rect().contains(i,{ifimage.setPixel(i,j,penColor().rgb());image.setPixel(i,j,qRgba(0,0,0,0));QPainterpainter(this);drawImagePixel(&painter,i,j);}}ThesetImagePixel()functioniscalledfrommousePressEvent()andmouseMoveEvent()tosetorclearapixel.Theposparameteristhepositionofthemouseonthewidget.ThefirststepistoconvertthemousepositionfromwidgetcoordinatestoimageThisisdonebydividingthexandycomponentsofthemousepositionbythezoomNext,wecheckwhetherthepointiswithinthecorrectrange.ThecheckiseasilymadeusingQImage::rect()andQRect::contains();thiseffectivelychecksthatiisbetween0andimage.width()–1andthatjisbetween0andimage.height()–1.apixelisreallysettingittobetransparent.Attheend,wecalldrawImagePixel()torepainttheindividualpixelthatchanged.Nowthatwehavereviewedthememberfunctions,wewillreturntotheWStaticContentsflagthatweusedintheconstructor.Thisflag lsQtthatthewidget'scontentdoesn'tchangewhenthewidgetisresizedandthatthecontentstaysrootedtothewidget'stop-leftcorner.QtusesthisinformationtoavoidneedlesslyrepaintingareasthatarealreadyshownwhenresizingtheNormally,whenawidgetisresized,Qtgeneratesapainteventforthewidget'sentirevisiblearea.ButifthewidgetiscreatedwiththeWStaticContentsflag,thepaintevent'sregionisrestrictedtothepixelsthatwerenotpreviouslyshown.Ifthewidgetisresizedtoasmallersize,nopainteventisgeneratedatall.5縮放一個(gè)WStaticContentsTheIconEditorwidgetisnowcomplete.Usingtheinformationandexamplesfromearlierchapters,wecouldwritecodethatusestheIconEditorasawindowinitsownright,asacentralwidgetinaQMainWindow,asachildwidgetinsidealayout,ortointegrateitwithQtDesigner.Doublebufferingisatechniquethatcanbeusedtoprovideasnappieruserinterfaceandtoeliminateflicker.Flickeroccurswhenthesamepixelispaintedmultipletimeswithdifferentcolorsinaveryshortperiodoftime.Ifthisoccursforonlyonepixel,itisn'taproblem,butifitoccursforlotsofpixelsatthesametime,itcanbedistractingfortheuser.WhenQtgeneratesapaintevent,itfirsterasesthewidgetusingthepalette'sbackgroundcolor.Then,inpaintEvent(),thewidgetonlyneedstopaintthepixelsthatarenotthesamecolorasthebackground.Thistwo-stepapproachisveryconvenient,becauseitmeanswecansimplypaintwhatweneedonthewidgetwithoutworryingabouttheotherUnfortunay,thetwo-stepapproachisalsoamajorsourceofflicker.Forexample,iftheuserresizesthewidget,thewidgetisfirstclearedinitsentirety,andthenthepixelsarepainted.Theflickerisevenworseifthewindowsystemshowsthecontentsofthewindowasitisresized,becausethenthewidgetisrepeatedlyerasedandpainted.6TheWStaticContentsflagusedtoimplementtheIconEditorwidgetisonesolutiontothisproblem,butitcanonlybeusedforwidgetswhosecontentisindependentofthesizeofthewidget.Suchwidgetsarerare.Mostwidgetstendtostretchtheircontentstoconsumealltheavailablespace.Theyneedtobecompleyrepaintedwhentheyareresized.Wecanstillavoidflicker,butthesolutionisslightlymorecomplicated.ThefirstruletoavoidflickeristoconstructthewidgetwiththeWNoAutoEraseflag.ThisflaglsQtnottoerasethewidgetbeforeapaintevent.Theoldpixelsarethenleftunchanged,andanynewlyrevealedpixelsareundefined.7WNoAutoEraseWhenusingWNoAutoErase,itisimportantthatthepainthandlersetsallthepixelsexplicitly.Anypixelthatisnotsetinthepainteventwillkeepitspreviousvalue,whichisn'tnecessarilythebackgroundcolor.Thesecondruletoavoidflickeristopainteverypixeljustonce.Theeasiestwaytoimplementthisrequirementistodrawthewholewidgetinanoffscreenpixmapandtocopythepixmapontothewidgetinonego.Usingthisapproach,itdoesn'tmatterThisisdoublebuffering.Addingdoublebufferingtoacustomwidgettoeliminateflickerisstraightforward.Supposetheoriginalpainteventhandlerlookslikethis:{QPainter}Thedouble-bufferedversionlookslike{staticQPixmappixmap;QRectrect=event->rect();QSizenewSize=rect.size().expandedTo(pixmap.size());pixmap.fill(this,rect.topLeft());QPainterpainter(&pixmap,this);bitBlt(this,rect.x(),rect.y(),&pixmap,0,0,rect.width(),rect.height());}First,weresizeaQPixmaptobeatleastaslargeastheboundingrectangleoftheregiontorepaint.(A"region"isveryofteneitherarectangleoranL-shapedarea,butitcanbearbitrarilycomplex.)WemaketheQPixmapastaticvariabletoavoidrepeatedlyallocatinganddeallocatingit.Forthesamereason,wenevershrinktheQPixmap;thecallstoQSize::expandedTo()andQPixmap::resize()ensurethatitisalwayslargeenough.Afterresizing,wefilltheQPixmapwiththewidget'serasecolororbackgroundpixmapusingQPixmap::fill().Thesecondargumenttofill()specifieswhichpointinthewidgettheQPixmap'stop-leftpixelcorrespondsto.(Thismakesadifferenceifthewidgetistobeerasedusingapixmapinsteadofauniformcolor.)TheQPixmapclassissimilartobothQImageandQWidget.LikeaQImage,itstoresanimage,butthecolordepthandpossiblythecolormaparealignedwiththedisy,ratherlikeahiddenQWidget.Ifthewindowsystemisrunningin8-bitmode,allwidgetsandpixmapsarerestrictedto256colors,andQtautomaticallymaps24-bitcolorspecificationsonto8-bitcolors.(Qt'scolorallocationstrategyiscontrolledbycallingQApplication::setColorSpec().)Next,wecreateaQPaintertooperateonthepixmap.Bypassingthethispointertotheconstructor,we lQPaintertoadoptsomeofthewidget'ssettings,suchasitsfont.Wetranslatethepaintertopaintthecorrectrectangleintothepixmap,beforeweperformthedrawingusingtheQPainterasusual.Finally,wecopythepixmaptothewidgetusingthebitBlt()globalfunction,whosenamestandsfor"bit-blocktransfer".Doublebufferingisnotonlyusefulforavoidingflicker.Itisbeneficialifthewidget'srenderingiscomplexandneededrepeatedly.Wecanthenstoreapixmappermanentlywiththewidget,alwaysreadyforthenextpaintevent,andcopythepixmaptothewidgetwheneverwereceiveapaintevent.Itisespeciallyhelpfulwhenwewanttodosmallmodifications,suchasdrawingarubberband,withoutputingthewholewidget'srenderingoverandWewillroundoffthischapterbyreviewingthePlottercustomwidget.Thiswidgetusesdoublebuffering,andalsodemonstratessomeotheraspectsofQtprogramming,includingkeyboardeventhandling,manuallayout,andcoordinateTheusercandrawarubberbandontheimage,andthePlotterwill|zoominontheareaenclosedbytherubberband.Theuserdrawstherubberbandbyclickingapointonthegraph,draggingthemousetoanotherpositionwiththeleftmousebuttonhelddown,andreleasingthemousebutton.8PlotterTheusercanzoominrepeatedlybydrawingarubberbandmultipletimes,zoomingTheZoomInandZoomOutbuttonsappearthefirsttimetheyeavailable,sothattheydon'tclutterthedisyiftheuserdoesn'tzoomthegraph.ThePlotterwidgetcanholdthedataforanynumberofcurves.ItalsomaintainsastackofPlotSettings,eachofwhichcorrespondstoaparticularzoomlevel.Let'sreviewtheclass,startingwithplotter.h:#ifndefPLOTTER_H#definePLOTTER_H#include<map>#include<vector>classQToolButton;classPlotSettings;typedefstd::vector<double>Weincludethestandard<map>and<vector>headerfiles.Wedon'timportallthestdnamespace'ssymbolsintotheglobalnamespace,becauseit'sbadstyletodothisinaheaderfile.WedefineCurveDataasasynonymforstd::vector<double>.Wewillstoreacurve'spointsassuccessivepairsofxandyvaluesinthevector.Forexample,thecurvedefinedbythepoints(0,24),(1,44),(2,89)isrepresentedbythevector24,1,44,2,classPlotter:publicPlotter(QWidget*parent=0,constchar*name=0,WFlagsflags=0);voidsetPlotSettings(constPlotSettings&settings);voidsetCurveData(intid,constCurveData&data);voidclearCurve(intid);QSizeminimumSizeHint()const;QSizesizeHint()const;publicslots:voidWeprovidethreepublicfunctionsforsettinguptheplot,andtwopublicslotsforzoominginandout.WealsoreimplementminimumSizeHint()andsizeHint()fromQWidget.voidpaintEvent(QPaintEvent*event);voidresizeEvent(QResizeEvent*event);voidmousePressEvent(QMouseEvent*event);voidmouseMoveEvent(QMouseEvent*event);voidmouseReleaseEvent(QMouseEvent*event);voidkeyPressEvent(QKeyEvent*event);voidwheelEvent(QWheelEventweneedtoreimplement.voidrefreshPixmap();voiddrawGrid(QPainter*painter);voiddrawCurves(QPainter*painter);enum{Margin=40};QToolButton*zoomInButton;QToolButton*zoomOutButton;std::map<int,CurveData>curveMap;intcurZoom;QRectrubberBandRect;QPixmappixmap;thewidget,andseveralmembervariables.TheMarginconstantisusedtoprovidesomespacingaroundtheAmongthemembervariablesispixmapoftypeQPixmap.Thisvariableholdsacopyofthewholewidget'srendering,identicaltowhatisshownonscreen.Theplotisalwaysdrawnontothisoff-screenpixmapfirst;thenthepixmapiscopiedontotheclass{voidscroll(intdx,intdy);voidadjust();doublespanX()const{returnmaxX-minX;}doublespanY()const{returnmaxY-minY;}doubleminX;doublemaxX;doubleminY;doublemaxY;voidadjustAxis(double&min,double&max,intThePlotSettingsclassspecifiestherangeofthexandyaxesandthenumberofticksfortheseaxes.Figure5.10showsthecorrespondencebetweenaPlotSettingsobjectandthescalesonaPlotterwidget.9PlotSettingsNowlet'sreviewtheimplementation#include<qpainter.h>#include<qstyle.h>#include<cmath>usingnamespacestd;#includeWeincludetheexpectedheaderfilesandimportallthestdnamespace'ssymbolsintotheglobalnamespace.Plotter::Plotter(QWidget*parent,constchar*name,WFlags:QWidget(parent,name,flags|{rubberBandIsShown=false;zoomInButton=newQToolButton(this);connect(zoomInButton,SIGNAL(clicked()),this,SLOT(zoomIn()));zoomOutButton=newQToolButton(this);omout.png"));zoomOutButton-connect(zoomOutButton,SIGNAL(clicked()),this,SLOT(zoomOut()));}ThePlotterhasaflagsparameterinadditiontoparentandname.Thisparameterissimplypassedontothebaseclassconstructor,alongwithWNoAutoErase.Theparameterisespeciallyusefulforwidgetsthatarelikelytobeusedasstand-alonewindows,becauseitallowstheuseroftheclasstoconfigurethewindowframeandtitlebar.ThesetBackgroundMode()calllsQWidgettousethe"dark"componentofthepaletteasthecolorforerasingthewidget,insteadofthe"background"component.adefaultcolorthatitmayusetofillanynewlyrevealedpixelswhenthewidgetisresizedtoalargersize,beforepaintEvent()evenhasthechancetopaintthenewpixels.SincethebackgroundofthePlotterwidgetwillbedark,itmakes

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論