Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 45 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
45
Dung lượng
587,47 KB
Nội dung
9.7 UsingSQL ModelClasseswithInterview UPDATE for thedataset as soon as th euserselects anotherdataset—that is, anotherrowin theview. SqlTableModel::OnFieldChange This transferseverychange to thedatabasedir ectlyafter theuserhas changed avalue in afield. SqlTableModel::OnManualSubmit This temporarilysaves allchanges in themodeluntil either th esubmitAll() slot,which transfersall changestothe database, or therevertAll()slotis triggered. Thelatter rejectsall cached dataand restores thestatusfromthe database(seeChapter 9.7.5onpage 270for more on therevertAll()slot). We willillustrate this last scenario bymodifyingthe exam plefrompage 265so that it additionallycontains twobuttons that arearrangedinalayoutbeneath the table view.All othercommandsare left as theyare. // sqlmvd/main.cpp(continued) QWidgetw; QPushButton * submitPb =newQPushButton( QObject::tr("SaveChanges")); QPushButton * revertPb =newQPushButton( QObject::tr("Roll back changes")); QGridLayout * lay=newQGridLayout(&w); QTableView * manualTableView=newQTableView; lay->addWidget(manualTableView,0,0,1,2); lay->addWidget(submitPb,1,0); lay->addWidget(revertPb,1,1); QSqlTableModel manualTableModel; manualTableModel.setTable("employees"); manualTableModel.select(); manualTableModel.setEditStrategy( QSqlTableModel::OnManualSubmit); manualTableView->setModel(&manualTableModel); QObject::connect(submitPb,SIGNAL(clicked(bool)), &manualTableModel, SLOT(submitAll()) ); QObject::connect(revertPb,SIGNAL(clicked(bool)), &manualTableModel, SLOT(revertAll()) ); w.setWindowTitle("manuallyrevertable table"); w.show(); returnapp.exec(); } Afterconverting theediting strategyto OnManualSubmit,weinserttwosignal/slot connections:Aclickonthe submitPb buttoncalls thesubmitAll()slot, whereas revertPbtriggers revertAll(). 269 9 TheQtSql Module Figure 9.5: With the OnManualSubmit editingstrategy, local changescan be transferredatany time youwanttothe database. Nowwemustnot forgettodisplaythemainwidgetwas thenewtop-level widget. Theresultisillustrated in Figure 9.5. 9.7.5Errorsinthe TableModel Several problems th at occurinconnectionwiththe table models in Qt 4.1should notbeleftunaddressedatthispoint.One is that editor operationsdonot always function reliablyafter columns havebeen removed.The QSqlRelationalTableModel even ignoresthe removeColumn() instructionentirely.Asaworkaround,aproxy modelthatfiltersout th eunwanted datasets is recommended here.Ifthe data should onlybe displayed,you can insteadsimplyplaceanSQL queryabovethe QSqlQueryModel. Anotherprobleminvolves therevertAll()slot, which is intendedtoundoall changes in relational tableswiththe OnManualSubmit editingstrategy.However,inthe columns in which aforeign keyrelation was previouslydefined withsetRelation(), revertAll()doesnot revertback to theold values. Theonlysolution until now was to connect theslotofthe buttonwithacustom-developedslotthatreplaces thecurrent modelwithanewonethathas thesameproperties. Since themodel temporarilysaves thedata, it will be lost in this way,and thenewmodelwilldisplay theoriginaldat afromthe database. 270 10 Chapter TheGraphics Library“Arthur” This chapter looksatthe drawingmethods of thecla ss librarythat Trolltechhas baptized “Arthur,” presumablyas areference to Microsoft’s “Avalon”technology.In this chapter wewillworkwithexamples that letusobservehowQt “paints” on buffers in thegraphicsand main memoryas wellasonwidgets andother devices, andwewillintroduce in detail theclassesbelonging to Arthur,together withtheir classicfields of application. Butfirstwemustexplainmorepreciselyhowdrawing reallyworks in Qt. Firstwewilllook at thecolor specificationsusedbyQt. 10.1Colors Color specificationsare of centralimportanceingraphic interfaces,including the issues of howcolors aregenerated andhowknowncolorsare namedsothatyou can workwiththemefficiently.The followingsection is devoted to thequestionof howdevelopers can manage colors. 271 10 TheGraphics Li brary“Arthur” 10.1.1The RGBColor Space Qt encapsulates colors in theQColor class. This is basedonthe RGBmodel, in which 8bits, representing arange of valuesfrom0to 255, areallocatedtoacolor. In addition,QColor specifies anothervalue,the so-called alphavalue,alsoreferred to as the alphachannel .Thisdefinesthe transparencyof apixel. QColor can also workwithvaluesother than integers. Foreach color command that accepts an integer,there exists afloating-point variation that allowscol- orstobespecifiedmoreprecisely.Whenever aQColor method that expectsin- teger colorinformation is discussedbelow,you can alwayssubstituteanassoci- ated floating-point variant instead, which accepts qrealvalues. Forexample, the setRgb()method, which expectsthree integer valuesfor thered,green,and blue colorcomponents andtakesanoptionalalpha value,has acorresponding floating- point equivalentcalledsetRgbF(). Thereare several waystogenerateanewQColor object.The basicQColor()con- structor creates an object withaninvalid color. Furthermore, thereisaconstructor that accepts colors describedusing integers. Thesemantics here correspondto thoseofsetRgb(). Thereisnoseparateconstructor that takesfloating-point num- bers as arguments, sincethiswould be ambiguous,asC++ automaticallyconverts integer valuestofloating-point values. To initializeacolorwithfloating-point val- ues, you first create an empty(and initiallyinvalid)QColor object,and then set colorvia setRgbF(). Earlierexamples often used yet anotherconstructor that accepts acolor chosen from 20predefinedcolorsthatare defined in theGlobalColor enumerator. This enumeration also includes valuesdescribinganumber of specialcases:The “color” Qt::transparent, for example, corresponds to QColor(0,0,0,0)and allowsaback- ground colortoshowthrough. In addition,QColor can deduce thedesired colorfromaname,asdefinedinthe SVG-1.0specification. 1 Forthispurposethe classhas aconstructor that accepts aQString or astring. ThesetNamedColor() method works in thesameway.This optionpermits anamed colortobeset later on,asillustrated in thefollowing example: QColorcolor("navy"); // sets adarkblue color.setNamedColor("royalblue"); // sets alightblue Thenames of allavailable namedcolorsare returned byQColor withthe color- Names()method. Finally,QColor hasaconstructorthatacceptsaQRgbvalue.QRgbinthiscaseis notaclassname, butaname,given byatype definition, for a32-bit integer.Given such avalue as an argument,thisconstructor sets theRGB valuesand thealpha 1 Seehttp://www.w3.org/TR/SVG/types.html#ColorKeywords. 272 10.1 Colors value of thenewQColor instance to thevaluesencodedinthe QRgbvariable. Theadvantage of QRgbasalightweightalternativefor transporting RGBcolor information is particularlyevidentwhenever largeamountsofpixel dat afroman image need to be read in. QRgbdivides theavailable bitsinthe 32-bit integer into fourinteger colorvalues, each consisting of eightbitsrepresentingvaluesfrom0to 255. This is doneas follows, in hexadecimalnotation(“A”=alphavalue,“R” =red,“G” =green,“B” = blue): 0xAARRGGBB Youdonot havetoconstruct yourownQRgbvalues, however:The help functions qRgb() andqRgba() take on th is task andexpect thecolor details to be provided in threeinteger arguments, as valuesbetween 0and255. qRgba()expectsthe al- phachannelasthe fourthargument.qRgb()omits thespecificationofthe alpha channel, andsets this componentofthe constructed QRgbvalue to 255 (corre- sponding to an opaque, that is,anontransparent, color).You can then accessthe individualQRgbcomponents via QRgb::qRed(), QRgb::qGreen(), QRgb::qBlue(), and QRgb::qAlpha(). Thesefunctionsreturn valuesfrom0to 255. Thefollowingexamplecreates ared,semitransparentQRgbvalue andpassesitto aQColor object,fromwhich wereadout thecolorsand thealpha ch an nelwiththe rgba() function andwrite it back to theQRgbvariable: QRgbrgba =qRgba(255, 0,0,127); // A=127,R=255, G=0,B=0 QColorcolor=QColor::fromRgba(rgba); rgba =0; // A=0,R=0,G=0,B=0 rgba =color.rgba(); // A=127,R=255, G=0,B=0 It is important here to usethe fromRgba() static method because thestandard constructor, which accepts aQRgbvalue,ignores thealpha channel. 10.1.2Other ColorSpaces In addition to RGB, QColor can also usethe HSVmodel, which defines acolor through hue, saturation,and brightness (or value)parameters. (HSV is therefore sometimesalsoreferredtoasHSB,where theBstands for brightness ,which is actuallyamoreprecise termfor thethird parameter.) TheHSV modelcorresponds most closelyto thehumanperceptionofcolor composition. To make useofit, wemustaccordinglyconvertthe color, via toHsv(). Then wecan read outthe HSVparameters, either componentwisevia hue(), saturation(), value(), andalpha(), or allatthe same time,using getHsv(): 273 10 TheGraphics Li brary“Arthur” QColorred(Qt::red); QColorred =red.toHsv(); inth, s,v,a; red.getHsv(&h, &s,&v,&a); // HSV valuesnowin h, s,v,a To specifyacolor in theHSV model, wehavethe setHsv() method, which expects thethree HSVcomponents as integersand,optionally,the alphachannel. If the alphavalue is missing,QColor assumesittobe255, that is, opaque . QColor is also able to acceptCMYK specificationsand to displaycolors specified in CMYK format. Since th ereare differences between thecolor spacesofthe RGBand CMYK models,however,and CMYK is asubtractivecolor modelwhereas RGBisan additiveone,not allcolorscan be represented in both colormodels.Incases where thereisnoexact equivalentfor adesired conversion from onesystem to theother, Qt triestoapproximatethe colorascloselyas possible. To obtain theCMYK representation of acolor,itissufficient to read outthe four colorcomponents andthe alphachannel, withgetCmyk(): QColorred(Qt::red); intc, m, y,k,a; red.getCmyk(&c,&m,&y,&k,&a); // CMYK valuesnowin c, m, y,k,a Here Qt calculates thematchingfour-colorvaluesingetCmyk()fromthe QColor’s internallystored RGBparameters. If aroutine of an applicationprogram requires thecolor to be specified in acolor modelother than RGBparticularlyoften,QColor can also representitinternallyin CMYK or HSV. In thesecases,noresources areused for conversion whenthe colorisaccessedvia getCmyk()orgetHsv(), respectively, buttheir interpretation as RGBcolorsisresourceintensive. To converttoanother colormodel, themethods toHsv(), toCymk(), andtoRgb() areused. Theconversion can be doneatanytime beforethe corresponding colorisaccessed: QColorred(Qt::red); // convert toCMYK internally QColorred =red.toCmyk(); intc, m, y,k,a; // no conversion required, alreadyconverted red.getCmyk(&c,&m,&y,&k,&a); // CMYK colors nowin c, m, y,k,a Youshouldonlyconvertpermanentlyto anothercolor model, however,ifyou have good reason to do so—internally,Qtusesthe RGBmodelnearlyeverywhere,which explains whyaclass is slower in operation after theinternalrepresentationofthe colors it uses is changedfromRGB to anothercolor model. ThesetCmyk()method defines acolor withCYMK details,and,inthe same wayas getCmyk(), reads in fourcolorsand,optionally,the alphachannel. 274 10.1 Colors 10.1.3Color SelectionDialog Thecolor selectiondialogQColorDialog(Figure 10.1,left) is specialized for these- lectionofcolorsdescribedusing theRGB model. 2 ItsAPI hasstaticmethods only. To read outanRGB value,getColor() is used: QColorcolor=QColorDialog::getColor(Qt::red, this); Thefirstparameter defines thecolor that thedialoginitiallyselects, andthe second describesthe obligatoryparentwidget, which can also be 0if themodalityof the dialog doesnot playanyrole.Ifthe user interruptsthe dialog, themethod returns an invalid color, which in this casecan be checkedwith!color.isValid(). Figure 10.1: QColorDialog:: getRgba() (right) differs from QColor- Dialog::getColor() (l eft) only in theinput field forthe alphachannel. Anothermethod calledgetR gba()can be used to definethe alphachannelfor a color(Figure 10.1,onthe right): bool ok; QRgbrgb=QColorDialog::getRgba(qRgba(255,0,0,127),&ok, this); QColorcolor(rgb); In contrast to getColor(), this method expectsaQRgbvalue.Since QRgbhas no dedicatedvalue for “invalid,” getRgba() againhas an ok parameter,which is setto false if Cancel is clicked. In this casegetRgba()returnsthe defaultvalue passed. The last lineshowshowyou can st oreaQRgbvalue (togeth er withits alphachannel) in aQColor object. bool ok; QColorcolor=Qt::red; color.setAlpha(127); color=QColorDialog::getRgba(color.toRgba(),&ok, this); 2 An HSVselection dialog is available as acommercialQtsolution. 275 10 TheGraphics Li brary“Arthur” QColorDialog allowsanumber of yourowncolors, in additiontothe defaultcolor, to be stored in aseparatepalette. Thenumber of fieldsavailable is defined bythe QColorDialog::customCount() static method. To setacolorinthispalette, thesetCustomColor() is used.Thismethod expectsthe palettepositionand thecolor as aQRgbvalue.The followingcallloads thefirst positionofthe palettewithasemitransparentred tone: QColorDialog::setCustomColor(0,qRgba(255, 0,0,127)); customColor() calls up thecolor in yourcustompaletteataparticular position. This method returnsthe QRgbvalue setfor theindexspecified: QRgbQColorDialog::customColor(0); Once theyareset, thecolorsapplyfor theentirelifetime of theapplicationfor all QColorDialog calls. 10.2Paintingwith Qt We willnowtake alook at thecla ssesthatpaint colors in specificshapes. As in real life, paintingtoolsand adrawingboardare necessary. Figure 10.2: Thebaseclass QPaint Device andits specializations QBitmap QPixmap QPicture QImage QPrinter QWidget QPaintDevice Painting toolsare bundledbyQt into theQPainter class. This can be used to both drawsimple brushstrokes andhandlemorecomplexgeometric forms,aswellas bitmaps.Awiderange of classesare eligible for useasthe drawingareas targeted byQPainter operations. Theyaredescendants of theQPaintDeviceclass.Each QPaintDevicecan thereforebearecipientfor QPainter operations. Theseinclude, amongothers, allwidgets andpixmaps,aswellasthe printinterface, QPrinter.An extensiveoverviewis showninFigure10.2. To start, here is asmall program that drawsafilled-in circle: // pixmap/main.cpp #include <QtGui> 276 10.2 Painting with Qt intmain(intargc, char * argv[]) { QApplication app(argc, argv); QPixmappm(100,100); pm.fill(); QPainterp(&pm); p.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::blue, 2); p.setPen(pen); QBrushbrush(Qt::green); p.setBrush(brush); p.drawEllipse(10,10,80,80); QLabel l; l.setPixmap(pm); l.show(); returnapp.exec(); } FirstwecreateanemptyQPixmapobject.The contents of this areinitiallyunde- fined,which is whywefill it withabasiccolor;whenitiscalledWithout afill color as an argument,fill()useswhite. Figure 10.3: Anti-aliasing minimizesformation of staircaseartifacts. Nowit is thepainter’s turn:Itperforms theactualdrawingoperations. So that thecir clelooksreallyround,and notsquare-edged, weswitch on anti-aliasing. This techniquesmooths theedgesthrough colorgradients,thus minimizingthe formation of steps(Figure 10.3). Beforesettingthe QPainter::Antialiasing flagto true,you should bear in mind that this can lead to significantlossofperformance, particularlyunder X11. Twosignificantpropertiesofapainter arecontained in additionalclasses. TheQPen defines howthepainter drawslines.Incontrasttothis, thepaintbrush, in theform of aQBrush,describeshowan area is filled, together wit hpatterns andtextures. In ourcasewewilluse abluepen,twopixelswide. We definethe paintbrushcolor as green,without apatternortexture.Wecan alreadydefinethese propertiesvia 277 10 TheGraphics Li brary“Arthur” theconstructors. Then webindthese newdefinitions to th epainter withsetPen() andsetBrush(). Finallyweuse aQPainter drawingmethod to actuallydrawthecircle. drawEllipse() drawsacircle,startingfromthe coordinates (10 , 10),inasquare of 80 × 80 pixels. Since wehaveset thesizeofthe whole image to 100× 100 pixels, thecir cleisright at thecenter of thepicture.Qtadheres to thestandardprogramming convention in which thecoordinates (0, 0) specifythetop left corner of thecurrent reference system.Inour casethisisthe topleftcornerofthe pixmapdefined. Figure 10.4: Ourpixmapina simplelabel We displaytheresulting image in aQLabel, which can displaypixmaps as wellas textifyou usethe setPixmap()method insteadofsetText(). (Thismethod expectsa referencetoaQPixmap.)The result is showninFigure10.4. 10.3Geometrical Helper Classes In theexamples just mentioned, wehaveplacedthe circle,using p.drawEllipse(10,10,80,80); in asquarewiththe side lengthsof 80 × 80 pixels, thelefttop corner of which is at thepoint (10 , 10).Ifwehad chosen twodifferent valuesfor height andwidth, this would haveresulted in aboundingrectangle insteadofaboundingsquare— anddrawEllipse() would havedrawnanellipse.Todescribe othergeometric objects, Qt provides theclassesQPoint, QSize, QRect, andQPolygon. TheQPointclass saves twocoordinates,without referencetoanexternalsystem. QSize, on theother hand,alsocombines twoparameterspassedinthe constructor, butinterpreted as aheightand awidth insteadofascoordinates,againwithout definingareference point.These object typesare united bytheQRect class, which generates arectangle:WhenpassedaQPoint andaQSizeasarguments, theQRect constructorinstantiates acorresponding rectangle. Alternatively,you mayusean 278 [...]... next to the square So that the distance from the square to the text is adjusted to the size of the font used, we select the width of the letter x in the respective font as the spacing For this purpose we add the corresponding width to the x component of the textStart point This variable now contains the top left point of our text The lower left point is determined by combining the right edge of legendRect... matrix that allows the coordinate system to rotate around the midpoint of the circle To do this we create a new matrix Since the center of the desired rotation is not the current zero point (origin) of the coordinate system, but the point at the center of the square, we first move the center of our square to the zero point of our coordinate system Then we rotate the matrix and move the point back to... define the dimensions of the chart These should exactly match the height of the widget We obtain this height value from the current size of the widget: 285 10 The Graphics Library “Arthur” rect() returns the size in the form of a QRect(), and we can extract the height from this with height() pieRect is now initialized to contain the rectangle in which we will later draw our pie chart We reserve the space... parameters: the widget height of the square of the pie,5 the longest entry in the hash table, the width of an x, the width of the legend square (fm) and the width of the 2 × 10 pixel–wide margin on both sides of the legend square We pack the height and width into an instance of QSize and return this 10.5.3 The Diagram Application In order to use the class, we instantiate the widget, add a few entries with values,... Practice be the same as the width The legend part should always be as wide as the longest text in the hash The minimum height is calculated from the number of legend entries and their vertical spacing The handler for the paint event and the reimplemented methods sizeHint() and minimumSizeHint() must take these conditions into account Before we can start painting, we first calculate the sum of all the values... setWindowTitle(tr("Screenshot")); } We now connect the clicked() signal of the Screenshot! button to the slot that prepares the screenshot, and the signal of the Print button to the slot that enables the configuration of the printing parameters Then we call grabDesktop(), which retrieves a screenshot from the current screen at the time the program is started It is intended merely as a substitute image for the previewLabel 10.9.1... adjust() call we move ten pixels further inward from all sides, so the rectangle becomes smaller This has the effect that we obtain ten pixels of space from the outer edges and from the right side of the pie graphics This causes the geometries for both parts of the widget to be dependent on the current widget size, and we proceed to draw the segments of the pie and the legend entries belonging to it,... in parts of 16 th of a degree, for reasons of precision angle therefore contains the actual number of degrees, multiplied by 16 We then select the current color using the colorPos variable from the colorNames list With a modulo calculation (%), we ensure that under no circumstances do we overwrite the end of the list, which means that if we were to run out of colors, we would just start assigning the. .. via pieRect() So that the gradient later “creases” the edge of the pie chart circle, thus creating the impression of spatial depth, we place the focus to the edge of the upper left region We achieve this by specifying a region, with pieRect.topLeft(), which actually lies outside the pie Between the center and the outer edge, we must also define at least two values for the course of the gradient We do this... 255 The following example reads out an image line by line and runs through the RGB values The result is also saved to a QImage The core of the program is the rotateRgb() method This creates a new QImage object of identical size and identical color format Then it opens the same array in both files and reinterprets the characters as a QRgb array The number of rows are defined by the height of the image, the . height); Then we define the dimensions of the chart. These should exactly match the height of the widget. We obtain this height value from the current size of the widget: 285 10 TheGraphics Li brary“Arthur” rect(). nowtime to drawthelegendtextnexttothe square.Sothatthe distan ce from thesquaretothe textisadjusted to thesizeofthe fontused, weselectthe width of theletter xin therespectivefontasthe spacing.For. determine the diameter via pieRect(). So that the gradient later “creases” the edge of the pie chart circle, thus creating the impression of spatial depth, we place the focus to the edge of the upper