C ++ GUI programmering med Qt4: Opprette dialogbokser.

Dette kapitlet er fra boken.

Dette kapitlet er fra boken.

Dette kapitlet er fra boken & # xF501;

2. Opprette dialogbokser.

Subclassing QDialog Signaler og spor i dybden Rapid Dialog Design Form-Changing Dialoger Dynamiske Dialogger Innebygd Widget og Dialog Klasser.

Dette kapittelet skal l re deg hvordan du oppretter dialogbokser ved hjelp av Qt. Dialogbokser presenterer brukere med alternativer og valg, og la dem sette inn alternativene til de foretrukne verdiene og til a gjore sine valg. De kalles dialogbokser, eller bare «dialoger», fordi de gir et middel som brukere og applikasjoner kan snakke med hverandre.

De fleste GUI-applikasjoner bestar av et hovedvindu med menylinje og verktoylinje, sammen med dusinvis av dialoger som utfyller hovedvinduet. Det er ogsa mulig a opprette dialogprogrammer som svarer direkte pa brukerens valg ved a utfore de aktuelle tiltakene (for eksempel en kalkulatorapplikasjon).

Vi vil lage var forste dialog bare ved a skrive kode for a vise hvordan det er gjort. Da ser vi hvordan du bygger dialoger ved hjelp av Qt Designer, Qts visuelle designverktoy. A bruke Qt Designer er mye raskere enn handkodning og gjor det enkelt a teste forskjellige design og endre design senere.

Subclassing QDialog.

Vart forste eksempel er en Finn-dialog som er skrevet helt i C ++. Det er vist i figur 2.1. Vi vil implementere dialogen som en klasse i sin egen rett. Ved a gjore det, gjor vi det til en uavhengig, selvstendig komponent, med egne signaler og spor.

Kildekoden er spredt over to filer: finddialog.h og finddialog.cpp. Vi starter med finddialog.h.

Linjer 1 og 2 (og 27) beskytter headerfilen mot flere inneslutninger.

Linje 3 inneholder definisjonen av QDialog, grunnklassen for dialoger i Qt. QDialog er avledet fra QWidget.

Linjene 4 til 7 er forhandsdeklarasjoner av Qt-klassene som vi skal bruke for a implementere dialogboksen. En forward-erkl ring forteller C ++-kompilatoren at en klasse eksisterer, uten a gi all detaljene som en klassedepartement (som vanligvis finnes i en headerfil av seg selv) gir. Vi vil si mer om dette snart.

Deretter definerer vi FindDialog som en underklasse av QDialog:

Q_OBJECT-makroen i begynnelsen av klassen definisjonen er nodvendig for alle klasser som definerer signaler eller spor.

FindDialog-konstruktoren er typisk for Qt-widgetklasser. Foreldreparameteren angir overordnet widget. Standard er null nullpeker, noe som betyr at dialogen ikke har noen forelder.

Signalseksjonen erkl rer to signaler som dialogboksen gir ut nar brukeren klikker Finn-knappen. Hvis alternativet Sok bakover er aktivert, utsender dialogen finne Tidligere (); Ellers sender den ut FindNext ().

Signalordet er faktisk en makro. C ++ preprocessoren konverterer den til standard C ++ for kompilatoren ser den. Qt :: CaseSensitivity er en enum type som kan ta verdiene Qt :: CaseSensitive og Qt :: CaseInsensitive.

I klassens private del erkl rer vi to spor. For a implementere sporene, ma vi fa tilgang til de fleste dialogboksenes barned widgets, sa vi holder ogsa pekere til dem. Slots sokeordet er, som signaler, en makro som utvides til en konstruksjon som C ++-kompilatoren kan fordoye.

For de private variablene brukte vi fremad deklarasjoner av sine klasser. Dette var mulig fordi de er alle pekere, og vi far ikke tilgang til dem i headerfilen, slik at kompilatoren ikke trenger de fullstendige klassdefinisjonene. Vi kunne ha medtatt de relevante headerfilene (& lt; QCheckBox & gt;, & lt; QLabel & gt;, etc.), men ved a bruke fremoverdeklarasjoner nar det er mulig gjor det noe raskere a kompilere.

Vi vil na se pa finddialog.cpp, som inneholder implementeringen av FindDialog-klassen.

Forst inkluderer vi & lt; QtGui & gt; , en headerfil som inneholder definisjonen av Qts GUI-klasser. Qt bestar av flere moduler, som hver bor i sitt eget bibliotek. De viktigste modulene er QtCore, QtGui, QtNetwork, QtOpenGL, QtScript, QtSql, QtSvg og QtXml. & Lt; QtGui & gt; headerfil inneholder definisjonen av alle klassene som er en del av QtCore og QtGui-modulene. Inkludert denne overskriften sparer oss for plaget av a inkludere hver klasse individuelt.

I finddialog.h, i stedet for a inkludere & lt; QDialog & gt; og ved bruk av fremdriftsdeklarasjoner for QCheckBox, QLabel, QLineEdit og QPushButton, kunne vi ganske enkelt ha medtatt & lt; QtGui & gt; . Det er imidlertid generelt darlig stil a inkludere en sa stor headerfil fra en annen headerfil, spesielt i storre applikasjoner.

Pa linje 4 overforer vi foreldreparameteren til baseklassekonstruktoren. Deretter lager vi barnets widgets. Tr () -funksjonen ringer rundt streng-bokstavene markerer dem for oversettelse til andre sprak. Funksjonen er erkl rt i QObject og hver underklasse som inneholder Q_OBJECT makroen. Det er en god vane a omgir bruker-synlige strenger med tr (), selv om du ikke har umiddelbare planer for a oversette applikasjonene dine til andre sprak. Vi dekker oversette Qt-applikasjoner i kapittel 18.

I streng-bokstavene bruker vi ampersands (‘& amp;’) for a angi hurtigtaster. For eksempel oppretter linje 11 en F ind-knapp som brukeren kan aktivere ved a trykke Alt + F pa plattformer som stotter snarveier. Ampersands kan ogsa brukes til a kontrollere fokus: Pa linje 6 lager vi en etikett med en snarvei (Alt + W), og pa linje 8 setter vi etikettens kompis som linjeditor. En kompis er en widget som aksepterer fokus nar etikettens hurtigtast trykkes. Sa nar brukeren trykker Alt + W (etikettens snarvei), gar fokuset til linjeditoren (etikettens kompis).

Pa linje 12, gjor vi Find-knappen til dialogboksen standardknapp ved a ringe setDefault (true). Standardknappen er knappen som trykkes nar brukeren treffer Enter. Pa linje 13, deaktiverer vi Find-knappen. Nar en widget er deaktivert, vises den vanligvis gratonet og vil ikke svare pa brukerinteraksjon.

Den private sporet enableFindButton (const QString & amp;) kalles nar teksten i linjeditoren endres. Den private sporet findClicked () kalles nar brukeren klikker Finn-knappen. Dialogen lukker seg nar brukeren klikker Lukk. Lukk () -sporet er arvet fra QWidget, og standardoppforelsen er a skjule widgeten fra visning (uten a slette den). Vi vil se pa koden for enableFindButton () og findClicked () slots senere.

Siden QObject er en av FindDialogs forfedre, kan vi utelate QObject :: prefikset foran forbindelsene (connect).

Deretter legger vi ut barned widgets ved hjelp av layout ledere. Layouter kan inneholde bade widgets og andre layouter. Ved a bygge QHBoxLayout s, QVBoxLayout s og QGridLayout s i ulike kombinasjoner, er det mulig a bygge sv rt sofistikerte dialoger.

For dialogboksen Finn bruker vi to QHBoxLayout s og to QVBoxLayout s, som vist i Figur 2.2. Ytre layout er hovedoppsettet; Den er installert pa FindDialog pa linje 35 og er ansvarlig for hele dialogboksen. De andre tre layoutene er deloppsett. Den lille «varen» nederst til hoyre i figur 2.2 er et mellomrom (eller «strekk»). Den bruker den tomme plassen under Finn og Lukk-knappene, slik at disse knappene opptar toppen av layoutet.

Figur 2.2 Finn dialogboksenes layouter.

Et subtilt aspekt av layout manager klassene er at de ikke er widgets. I stedet er de avledet fra QLayout, som igjen er avledet fra QObject. I figuren er widgets representert av faste konturer og layoutene er representert av stiplede konturer for a markere forskjellen mellom dem. I et lopende program er oppsettene usynlige.

Nar underlayouts legges til i overordnet layout (linjer 25, 33 og 34), blir underlayouts automatisk reparert. Da, nar hovedoppsettet er installert pa dialogboksen (linje 35), blir det et barn i dialogboksen, og alle widgets i layoutene blir reparert til a bli barn i dialogboksen. Det resulterende foreldre & ndash; barnhierarkiet er avbildet i Figur 2.3.

Figur 2.3 Finn dialogboksen foreldre & ndash; barns forhold.

Til slutt setter vi tittelen som skal vises i dialogboksens tittellinje, og vi stiller vinduet for a ha en fast hoyde, siden det ikke finnes noen widgets i dialogboksen som meningsfullt kan oppta ekstra vertikal plass. QWidget :: sizeHint () -funksjonen returnerer en widgets «ideelle» storrelse.

Dette fullforer anmeldelsen av FindDialogs konstruktor. Siden vi brukte nytt for a lage dialogboksens widgets og layouter, virker det som om vi ma skrive en destructor som kaller slett pa hver widget og layout vi opprettet. Men dette er ikke nodvendig, siden Qt sletter automatisk barnobjekter nar foreldrene er odelagt, og barnets widgets og oppsett er alle etterkommere av FindDialog.

Na ser vi pa dialogens spor:

FindClicked () -sporet heter nar brukeren klikker Finn-knappen. Den avgir det forrige () eller findNext () signalet, avhengig av alternativet Sok bakover. Emitteringsnavnet er spesifikt for Qt; I likhet med andre Qt-utvidelser blir den omgjort til standard C ++ av C ++ preprosessoren.

Sla pa enableFindButton () -sporet nar brukeren endrer teksten i linjeditoren. Det aktiverer knappen hvis det er noe tekst i redigeringsprogrammet, og deaktiverer det ellers.

Disse to sporene fullforer dialogen. Vi kan na opprette en main.cpp-fil for a teste var FindDialog-widget:

For a kompilere programmet, kjor qmake som vanlig. Siden FindDialog klassen definisjon inneholder Q_OBJECT makroen, vil makefilen generert av qmake inneholde spesielle regler for a kjore moc, Qts meta-objekt kompiler. (Vi dekker Qts meta-objekt-system i neste avsnitt.)

For at moc skal fungere riktig, ma vi sette klasses definisjonen i en headerfil, adskilt fra implementeringsfilen. Koden som genereres av moc, inneholder denne headerfilen og legger til noen C ++-boilerplate-koden av seg selv.

Klasser som bruker Q_OBJECT makroen ma ha moc kjor pa dem. Dette er ikke et problem fordi qmake automatisk legger til de nodvendige reglene for makefile. Men hvis du glemmer a regenerere din makefile ved a bruke qmake og moc ikke kjores, vil linkeren klage pa at noen funksjoner er deklarert, men ikke implementert. Meldingene kan v re ganske uklare. GCC produserer feilmeldinger som denne:

Visual C ++ ‘s utgang starter slik:

Hvis dette noen gang skjer for deg, kjor qmake igjen for a oppdatere makefile, og bygg deretter programmet pa nytt.

Kjor na programmet. Hvis hurtigtaster vises pa plattformen, ma du kontrollere at hurtigtastene Alt + W, Alt + C, Alt + B og Alt + F utloser den rette oppforselen. Trykk pa Tab for a navigere gjennom widgets med tastaturet. Standardfanordren er den rekkefolgen der modulene ble opprettet. Dette kan endres ved hjelp av QWidget :: setTabOrder ().

A gi en fornuftig kategoriordre og tastatursnarveier sikrer at brukere som ikke vil (eller ikke kan) bruke en mus, er i stand til a utnytte programmet fullt ut. Fullt tastaturkontroll er ogsa verdsatt av raske maskinskrivere.

I kapittel 3 vil vi bruke dialogboksen Finn i en ekte applikasjon, og vi vil koble finneForrige () og finnNeste () signaler til noen spor.


Hei! Vil du spille i det mest populære kasinoet? Vi forbereder det for deg. Prøv her nå!