The book of qt 4 the art of building qt applications - phần 3 pptx

45 308 0
The book of qt 4 the art of building qt applications - phần 3 pptx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

3.1 Dialogs“By MouseClick” Figure 3.9: Signal/slot connectionsare createdinthe Designer vi adragand drop. Step twoconsistsofspecifyingthe desiredsignaland slot pairfor thetwowidgets. As soon as you releasethe mousebuttonover thetargetwidget, theDesigner opens adialog, as showninFigure3.10:Onthe left it showsamenu of themost frequentlyused signals. If thesignalyou arelookingfor is notthere,clickthe Show allsignals andslots checkboxto displayallpossible signalsofthe source widget. Theright selectionboxwill showallthe slotsofthe target wid getmatchingthe signal selected on theleft. If you confirm thechoice, theconnectionisestablished. Figure 3.10: Signals andslots of twoselectedwidgets areconnectedbythe developerinthis dialog. Aclickonthe connectingline, followed bypressing the ✞ ✝ ☎ ✆ Del key,willremovethe connection. 3.1.5The TabSequence Theso-called tabsequence is important for keyboardusers. This function allows theinput focustobeshifted,via the ✞ ✝ ☎ ✆ Tab key,tothe nextwidgetthatexpects input. TheDesignerspecifiesthe tabsequencesothatinitiallythefirstwidgetin thedialoghas thekeyboardfocus.The focusismoved to th enextinserted GUI elementwhenthe ✞ ✝ ☎ ✆ Tab keyis pressed. When designingauser interface, you should 89 3 GUI Design Usingthe Qt Designer payattention to thedefault tabsequenceand modifyit as necessaryin orderto make yourapplicationasuserfriendlyas possible. Figure 3.11: Howthe focusis passedonwhen pressingthe ✞ ✝ ☎ ✆ Tabkey is specifiedinthe Tab Ordermode To do this,you switch to the TabOrder mode,via Edit → EditTab Orderorthe icon withthe numbers123 andanarrowin thetoolbar. NowtheDesignerdisplayseach widget’scurrent positioninthe tabsequenceinabluebox(Figure3.11).Aclickon thecorresponding boxincreasesthe rank in thesequencebyone. 3.1.6Shortcutsand Buddies Thosewho prefer keyboardcontrol willthank you if theycanjump directlyto as manycommonlyused widgets as possible.GUI elements that displayauser- defined text, such as buttons,are assigned akeyabbreviation byplacingan am- persand (&)beforethe characterthatwillserveasthe keyboardshortcut. If the textitselfcontainsareal ampersand, it is masked byduplicatingit: &&. If theuserpressesthe combinationof ✞ ✝ ☎ ✆ Alt + ✞ ✝ ☎ ✆ character from nowon,the widget obtainsthe focusand is activated.InFigure3.12weuse this techniquewiththe Quit button. QLabel objectsformanexception, however.Since theyusuallyoccurinalayout for thepurposeofdescribinganadjacent“partner” widget, theythemselves do notaccept afocus.However,the Buddypropertyof alabel can be used to spec- ifyakeyboardshortcuttobeassociatedwiththe partnerwidget, as though the descriptivetextofthe labelweredir ectlyattached to thepartner elementitself. In theDesignerviewmode EditBuddies,you can nowspecifywithwhich widget alabel is apartner.Todothis, clickthe future Buddylabel, which willthenlight up in red. Holdingdownthe mousebutton, you nowpull aconnectionover to the widgetthatinfutureshouldbeassociatedtothe label. 90 3.2 IntegratingDesigner-generatedFiles into Your Qt Project Figure 3.12: Labels arefriendsto other widgets:The Buddy allocationscan be found in theBuddy mode of theQt Designer. In theexamplefromFigure3.12, th erespectivelineeditnowhasthe focusifthe user pressesthe lettersunderlined in thelabel inscriptionwhile holdingdownthe ✞ ✝ ☎ ✆ Alt key. Alternatively,while in thenormaldesignmode,you can setthe name of thede- siredBuddywidgetinthe PropertyEditor, usingthe Buddyproperty. 3 Using this ap- proach,wewould setthe value of th eBuddypropertyof theQLabelobject that dis- playsthe Decimaltextinour byte converter dialog so that it matchesthe value of theobjectNamepropertyof thecorresponding line-edit object,namely,the string decEdit. To undothe relationship,all you need to do is clickthe connectionlineinthe Buddy mode andpress the ✞ ✝ ☎ ✆ Del key. 3.2IntegratingDesigner-generated FilesintoYour Qt Project When savingwiththe menu item File→ SaveFormorSaveFormAs. ,theDesigner generates a.ui filefromthe information it hasfor each widgetinthe form. 4 This .uifile is specified in theqmake projectfile,asshowninthe followingline: FORMS=byteconverterdialog.ui In ourcase, qmaketakesintoaccount theuserinterfacefile byteconverterdialog.ui; several files can be specified,separated byaspace, or otherlines can be added according to thepatternFORMS+= file.ui . 3 Althoughthispropertyhasbeen theresince Qt 3.x ,the Designer forQt4.0doesnot displayit. Onlyin version 4.1doesitappear again. 4 Using thethird menu item,SaveFormAsTemplate. , you cansaveyourformasatemplate, which then appearsinthe selectiondialogfor new Fo rms . 91 3 GUI Design Usingthe Qt Designer When buildingthe project, make then reliesonthe user interface compiler uic to convertDesigner-generated .uifilesintoC/C++headerfiles. 5 Thereisafixed naming convention in this step:for example, if theclass represented bythe.ui file generated bytheDesigneriscalledByteConverterDialog (the value of theobject- Name propertycan be examined to determine th eclass name), then theresulting headerfile is given thenameui_byteconverterdialog.hbyuic. It is important here that at leastone otherfile in theproject includes this generated headerfile.You mustadd theappropriate #include statemen ts before qmakeis run. Otherwise, make won’t calluic withthe relevantinterfacedescription fileas an argument on itsnextrun. Notice that thegenerated headerfile contains onlyahelpclass withtwomethods: setupUi(), which generates theGUI,and retranslateUi(), which can be calledifthe program is to allowtheusertochangethe language while it is running. Bothmethods expect (asanargument)apointer to th ewidgettowhich th eGUI object describedinthe Designer is to be bound.Even if you havealreadychosen a template in theDesigner, you can freelychooseatthispoint thewidgetclass for which theinterfaceisintended. TheMainWindowtemplate is theonlyonethat mustbeusedtogether withaQMainWindow. 6 Theclass generated bytheuic is nowavailable as Ui::ByteConverterDialog or Ui_ ByteConverterDialog,ingeneral as Ui::classname or Ui_ classname ,wherebythe classnamecorresponds to theobjectNameattribute of theformcreated in the Designer. Thereare nowthreewaysofusing andfunctionallydeveloping thewidgetcreated. Whichofthese is best to usedepends on theparticularcontext. 3.2.1Using Designer-generatedClassesasHelperClasses If you onlywanttodisplayaDesigner-created user interfaceonce, without touch- ingthe corresponding object againafter it is initialized,itisappropriate to directly instantiatethe generated classand bindthe instance to apreviouslycreated widget withsetupUi(). This method fixes theGUI elements describedinthe .uifile on to thewidgetand anchorsthem—provided this was specified in theDesigner—with layouts. We shalldemonstrate this techniqueusing ourDesigner-generated ByteConverter- Dialog: 5 Note forQt3users: uicnolongergenerates acompleteQObject-based classinQt4,but merely aframework which canbeappliedtothe widgetofthe matching type. 6 Thewidgetcreated in theDesignerisusedinthiscaseasthe centralwidgetfor th eQMainWin- dowinstance, anditispositionedwithsetCentralWidget(), instead of withthe help of alayout, as normal.Inaddition,the Designer menu bars andtoolbars aretreated separatelyfrom Qt 4.1, afunctionalitythat is equallyavailable onlyforQMainWindowinstances. 92 3.2 IntegratingDesigner-generatedFiles into Your Qt Project // simple/main.cpp #include <QtGui> #include "ui_byteconverterdialog.h" intmain(intargc, char * argv[]) { QApplication app(argc, argv); QDialog dlg; Ui::ByteConverterDialog ui; ui.setupUi(&dlg); dlg.setAttribute(Qt::WA_QuitOnClose); dlg.show(); returnapp.exec(); } Since thewidgets of theDesigner-generated dialog areavailable as publiclyac- cessible membersofthe UI class, theycanbefine-tunedinthe code later on by callingthe methods of therespectivewidgets.Their signalsand slotscan partici- pateinsignal/slot connections.Whether th eclass Ui::ByteConverterDialog is now instantiated in themain() function or in theconstructor of aclass inheriting from QDialog makesnodifference. In ourexample, however,the approach showninthe listing abovecausesproblems: We couldcon nect theQuitbutton’sclickedsignaltothe accept()slotofthe dialog, andwewould then be able to connect theslots binChanged(), hexChanged(), and binChanged()tothe textChanged() signalsofthe respectiveQTextEditwidgets.But then wewould notbeable to accessthe pointer to anyuic-generated widgetin theslotitself. Forthisreason, theuse of directlycallingsetupUi()isverylimited:Ifwedoso, weshall restrict ourselves to applyinginstances of theclass generated byuicto instancesofastandardclass likeQWidgetorQDialog.However,insomesituations this procedurecould be completelysufficient, for example, in simple modal input dialogs which arecalledwithexec(). Theexec callstartsaseparateeventloop andreturnsonlyif accept(), reject (), or anothermethod closes thedialog. Sin ce thedialogobject doesnot ceasetoexistwhenthe dialog hasbeen closed,the subsequent code can fetchthe valuesofthe widgets placed inside thedialogby setupUi()without an ydanger, so that you can getbywithout theQDialog subclass in thosecases. It is important that you alwayscallthe setupUi()method of an instance of a Designer-generated classfirst, beforetryingtoaccess member variablesofthe in- terfaceobject (inthe currentexample, thoseofui).Otherwise, theprogram will mess around withuninitialized pointersand crash. An argument for notinstanciating Designer-generated classesdir ectlyresultsfrom thefact that public-membervariblesare accessible from theoutside,causing a 93 3 GUI Design Usingthe Qt Designer violation of secrecy,one of themostimportant principles of object-oriented pro- gramming.Secrecyenforcesabstractionbyonlygranting theclass membersaccess to theirownmethods. Theinternaldetails of theclass arethus “cut off” from theother classes, andyou can change theinternaldesignofthe classwithout havingtoadjustthe rest of the program that uses this class. As long as you useonlytheUIclass as ashort-term setupclass ,the infringement of theencapsulationprinciple is notreallyof any consequence. 3.2.2AlwaysHavingDesigner-generatedWidgets Available In ordertodealwiththe shortcomingjustdemonstrated,itisagood idea to include theclass generated byuicasamember variable.Todothis, wefirstinheritfrom thedesired class, which in ourcaseisQDialog. Themain() function matchesthe onefromChapter 2, sinceByteConverterDialog from itspoint of viewis againa“black box.” Thecrucial differenceisinthe declaration of theclass .Wedeclare theclass gen- erated byuicasaprivatememberofaQDialog subclass .Thisallowsfor abitrary accesstothe widgets withinthe Designer-generated classvia this newlycreated ui member variable of theByteConverterDialog classinherited from QWidget: // member/byteconverterdialog.h #include <QDialog> #include "ui_byteconverterdialog.h" class QLineEdit; class ByteConverterDialog :public QDialog { private: Ui::ByteConverterDialog ui; } ; Theconstructor an dall slotsnowaccessthe generated classvia theuimember variable: // member/byteconverterdialog.cpp ByteConverterDialog::ByteConverterDialog(QWidget * parent) :QDialog(parent) 94 3.2 IntegratingDesigner-generatedFiles into Your Qt Project { ui.setupUi(this); connect(ui.decEdit,SIGNAL(textChanged(const QString&)), this,SLOT(decChanged(const QString&))); connect(ui.hexEdit,SIGNAL(textChanged(const QString&)), this,SLOT(hexChanged(const QString&))); connect(ui.binEdit,SIGNAL(textChanged(const QString&)), this,SLOT(binChanged(const QString&))); } void ByteConverterDialog::decChanged(const QString&newValue) { bool ok; intnum=newValue.toInt(&ok); if (ok) { ui.hexEdit->setText(QString::number(num, 16)); ui.binEdit->setText(QString::number(num, 2)); } else { ui.hexEdit->setText(""); ui.binEdit->setText(""); } } Theoverlyingprinciple also applieshere: It is essentialthatsetupUi()iscalledfirst beforewecan usethe UI classinanywayat all. Thedisadvantage of this method is itsindirectness, via themembervariable.But theadvantage of this approach is that it defusesthe encapsulation problem, limitingthe problemtoscope of the dialog class. Anysinceaccess from outsideofthe dialog is notpossible under any circumstances.Afurtherbonus:Itisclear from thecode which widgets weregen- erated in theDesigner. In addition,thisapproachisparticularlysuited for widgets in librariesthathavetoremainbinary-compatible,because onlythepointer to the instance of thegenerated classchanges thebinarylayoutinthe compileroutput. 7 3.2.3MultipleInheritance As the idealsolution, Trolltechrecommendsmultipleinheritance. Butlikethe pre- vious solution,thisworks onlyif you plan yourownsubclass. In this method, thenewwidgetinherits notonlyfrom QWidget, butalsofromthe UI classgen erated byuic. Aparticularhighlight is theuse of theprivatekeyword in theinheritanceinstruction.Thisensures that allmethods from theUIclass 7 More details of binarycompatibilityin C++havebeen compiledbytheKDE projectat http://developer.kde.org/documentation/other/binarycompatibility.html. 95 3 GUI Design Usingthe Qt Designer aregiven th estatusofprivateclass variablesinthe newclass, although theyare actuallypubliclyaccessible in theformerclass itself: // inherit/byteconverterdialog.h class ByteConverterDialog :public QDialog, privateUi::ByteConverterDialog This method thus solves several problems at onestroke: We can usethe widget pointersgenerated byuicasstandardmembervariables, without going thelong wayround,via ahelpobject,and theyremain private, so that encapsulation to the outsideismaintained. Forour example, this meansthatthe constructorchanges as follows: // inherit/byteconverterdialog.cpp ByteConverterDialog::ByteConverterDialog(QWidget * parent) :QDialog(parent) { setupUi(this); connect(decEdit,SIGNAL(textChanged(const QString&)), this,SLOT(decChanged(const QString&))); connect(hexEdit,SIGNAL(textChanged(const QString&)), this,SLOT(hexChanged(const QString&))); connect(binEdit,SIGNAL(textChanged(const QString&)), this,SLOT(binChanged(const QString&))); } void ByteConverterDialog::decChanged(const QString&newValue) { bool ok; intnum=newValue.toInt(&ok); if (ok) { hexEdit->setText(QString::number(num, 16)); binEdit->setText(QString::number(num, 2)); } else { hexEdit->setText(""); binEdit->setText(""); } } As before, weonlyneed to callthe setu pUi()method in first position, an dasthe argument weagainuse apointer to thewidgetthatisour currentclass scope. 96 3.3 AutomaticSignal/SlotConnections Caution: In this approach theinheritancesequenceisimportant.First theclass mustinheritfromQDialog,and then from theDesignerclass.Ifthisisnot thecase, thecom pilerwillthrowan errorthatisdifficulttounderstand, andwhich quickly brings theprogrammertodespair: moc_byteconverterdialog.cpp:43:error:‘staticMetaObject’ isnota memberof type‘Ui::ByteConverterDialog’ moc_byteconverterdialog.cpp:Inmemberfunction ‘virtualvoid * ByteConverterDialog::qt_metacast(const char * )’: moc_byteconverterdialog.cpp:60:error:’class Ui::ByteConverterDialog’ hasno membernamed ’qt_metacast’ moc_byteconverterdialog.cpp:Inmemberfunction ‘virtualint ByteConverterDialog::qt_metacall(QMetaObject::Call, int,void ** )’: moc_byteconverterdialog.cpp:66:error:’class Ui::ByteConverterDialog’ hasno membernamed ’qt_metacall’ make: *** [moc_byteconverterdialog.o]Error1 Thereasonisthe behaviorofthe meta-object compiler, which checks onlyin the first parentclass of theinheritancelistwhether this inherits from QObject or not. This also meansthatitisgenerallynotpossible to inheritfromseveral classesthat allhaveQObject as abaseclass. 3.3Automatic Signal/SlotConnections Developers versedinVisualBasic or Delphi who startonQt/C++developmentfind thesignal/slot conceptunusual, andtheymiss theeventhandler.Qt4allowsthem to sticktothe semanticstheyareusedto, permitting slot declarationsofthe form void on objectname signalname(); that areconverted into connect() instructions that uicsaves in setupUi(). Inciden- tally,thisnamingconvention increasesthe readabilityof thesourcetext. Thewhole point of this functionalityis thestaticQMetaObject::connectSlotsBy Name() method: It expectsapointer to aQObject andsearchesthrough it for slotswithmatchingnames.ThenQMetaObject::connectSlotsByName() connects thefound slotswiththe appropriate signal.Todothisitusesinformation from the meta-object generated bythemeta-object compiler, moc. This meta-object adds thecapabilityknowninC++ as introspection (alsoknowninJavaas reflectio n )to allclassesinheriting from QObject.Atruntimethe classtherefore“knows” itsmeth- ods,signals,and slots. connectSlotsByName() recursivelylooksatthe sl ot namesof theobject behind thepointersand allits children, connectingthe respectivesignals to them. Trolltechrecommendsthe semanticsshownaboveonlywiththe Designer-genera- ted classes, sinceinthiscasethe object name andthe name of theuic-generated 97 3 GUI Design Usingthe Qt Designer pointer to thewidgetmatch,and because th esetupUi()method subsequentlycalls connectSlotsByName(). Butfor thosewho findthisconsistentnamingpatternirre- sistible,all therelevantobjectsmustbeassigned anamevia setObjectName(), must be calledinthe constructororfromoutside QMetaObject::connectSlotsByName(), andmustpassapointer to thecurrent class(this)tothiscall. Because theshownsemantics areverypronetoerrors, 8 you should useautomatic connectiononlywithDesigner-generated widgets withmultipleinheritance. We wil lmodifyourexamples from abovesothatthe slot namesfollowthecon- ventionsfor automaticconnection. At thesametimethe connect() calls in the constructorcease to apply,sothatonlythesetupUi()instruction is left: // autoconnect/byteconverterdialog.h privateslots: void on_decEdit_textChanged(const QString&); void on_hexEdit_textChanged(const QString&); void on_binEdit_textChanged(const QString&); // autoconnect/byteconverterdialog.cpp ByteConverterDialog::ByteConverterDialog(QWidget * parent) :QDialog(parent) { setupUi(this); } void ByteConverterDialog::on_decEdit_textChanged(const QString&newValue) { bool ok; intnum=newValue.toInt(&ok); if (ok) { hexEdit->setText(QString::number(num, 16)); binEdit->setText(QString::number(num, 2)); } else { hexEdit->setText(""); binEdit->setText(""); } } 8 Remember that onlytheobject name is relevantand that in this procedure, Qt cannotissue warningsabout connections th at fail at runtime. 98 [...]... using the Designer, which allows the basic graphical framework of most applications to be put together “by mouse click” in Qt versions 4. 1 and later The basis of this is the QMainWindow Qt class 4. 1 The Anatomy of the Main Window The QMainWindow class forms the basis of an application window: Menu bar, status bar, toolbars, and dock windows can be brought into this main window Figure 4. 1 shows the individual... Based on a Main Window the user friendliness of the software They should therefore be provided as a matter of course in the design of user interfaces With the accelerators in place, the design view of the editor should correspond to that shown in Figure 4. 3 To define the subitems of an individual menu entry, we select the entry in the menu bar A drop-down menu then appears and, for each desired subitem,... one with a value of 2, then they jointly occupy the entire space in the status bar so that the second one is twice as wide as the first In the example of Figure 4. 8, whose five widgets have been assigned stretch values of 1, 2, 3, 4, and 5, the first widget is only allocated the space it requires The other widgets occupy the remaining space so that the third one has twice as much space as the second, and... list of already opened resource files It does not include a save action, as this is performed implicitly by the editor 9 Notes on this are provided in the online documentation for Qt 99 3 GUI Design Using the Qt Designer Figure 3. 14: The resources example from page 57 in the Resource Editor of the Designer In addition, the list of resources displayed in the Designer is independent of those in the pro... widget in the Designer and click it with the right mouse button after it has been adjusted From the context menu, you now select the entry Promote to Custom Widget In the dialog that appears (see Figure 3. 13) , you specify the name of the new class and that of its header file Although the Designer continues to show the original Qt widget, the finished program uses the modified widget; so in the implementation... include them in the same toolbar, as is the case in Figure 4. 5, you should separate them from the other entries in the File menu with a separator (right mouse button →Insert Separator) Actions have other properties that the Property Editor allows to be set These include the application-wide shortcut (the so-called shortcut) In contrast to ac✞ ☎ celerators, shortcuts are activated with the ✝ ✆ The user... since the Designer does not take them into account 3. 5 The Resource Editor From Qt 4. 1 on, the Designer supports the setting up and administration of the resources already discussed on page 57 The editor integrated in this (Figure 3. 14) can be called from the entry Tools → Resource Editor, in case it is not already visible Navigating in it takes some getting used to, however The drop-down box next to the. .. all the descriptions from Chapter 3 apply In particular, just as explained there, the user interface compiler uic creates a class from the ui file generated by the Designer; the setupUi() method then “decorates” a main window to a certain extent After the Designer has started, we select the Main Window item from the template menu When designing our editor window, we borrow ideas from the designs of other... Qt uses the program name as the title text We set the text for the title bar via the tr() method, which inherits MainWindow inherits from QObject If the user wants, this will translate the text to another language at runtime; if not, it returns the string unchanged .4 The resize() function that MainWindow also inherits from QWidget specifies the size of the window The two arguments determine the width... aligned at the left margin To center text in both directions, we change the alignment with setAlignment() This function takes as an argument values from the enumeration type (enum) alignment, which is defined in the Qt namespace5—hence the value AlignCenter is prefixed with Qt: : 4 5 See also page 49 and Chapter 14 from page 37 5 for a detailed discussion Qt uses the namespace Qt for a large number of enumeration . can setthe name of thede- siredBuddywidgetinthe PropertyEditor, usingthe Buddyproperty. 3 Using this ap- proach,wewould setthe value of th eBuddypropertyof theQLabelobject that dis- playsthe Decimaltextinour. usingthe Designer,which allowsthe basicgraphical frameworkofmostapplications to be puttogether “bymouseclick” in Qt versions 4. 1and later .The basisofthisisthe QMainWindowQt class. 4. 1The Anatomy of. performedimplicitlybytheeditor. 9 Notesonthisare provided in theonlinedocumentationfor Qt. 99 3 GUI Design Usingthe Qt Designer Figure 3. 14: Theresources example from page 57 in theResource Editor of theDesigner In

Ngày đăng: 13/08/2014, 08:21

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan