Getting Started on the Commandline/nl: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[toc align_right= | [toc align_right="yes" depth="3"] | ||
= Beginnen met programmeren in Qt = | = Beginnen met programmeren in Qt = | ||
Welkom in de wereld van Qt — de cross-platform GUI toolkit. In deze | Welkom in de wereld van Qt — de cross-platform GUI toolkit. In deze "getting started guide" zullen we u basis Qt kennis bijbrengen door een simpele kladblok applicatie te maken. Na het lezen van deze oefening, zult u klaar zijn om in onze overzichten en API documentatie te duiken, en alle informatie te vinden die u nodig heeft voor de applicatie die u ontwikkelt. | ||
== Hallo Kladblok == | == Hallo Kladblok == | ||
Line 11: | Line 11: | ||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | ||
Hier is de code:<br /><code>#include | Hier is de code:<br /><code>#include <QApplication><br />#include <QTextEdit> | ||
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | ||
Line 17: | Line 17: | ||
QTextEdit textEdit;<br /> textEdit.show(); | QTextEdit textEdit;<br /> textEdit.show(); | ||
return app.exec | return app.exec();<br />}</code> | ||
Laten we dit stuk code regel voor regel doornemen. In de eerste twee regels includen we de header files voor | Laten we dit stuk code regel voor regel doornemen. In de eerste twee regels includen we de header files voor "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html en "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, die de twee classes zijn die we voor dit voorbeeld nodig hebben. Alle Qt classes hebben een header met zelfde naam. | ||
Regel 6 creëert een | Regel 6 creëert een "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html object. Dit object beheert alle resources die nodig zijn voor een Qt applicatie met een GUI. Het heeft argv en args nodig omdat Qt applicaties enkele command line argumenten accepteren. | ||
Regel 8 creert een | Regel 8 creert een "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html object. Een text edit is een visueel element in de GUI. In Qt noemen we dit soort elementen widgets. Voorbeelden van andere widgets zijn scroll bars, labels en radio knoppen. Een widget can ook een container zijn voor andere widgets, een dialog of een main applicatie bijvoorbeeld. | ||
Regel 9 toont de text edit op het scherm in zijn eigen window frame. Omdat widgets ook als containers functioneren (bijvoorbeeld een | Regel 9 toont de text edit op het scherm in zijn eigen window frame. Omdat widgets ook als containers functioneren (bijvoorbeeld een "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, die toolbars, menus, een status bar, en een aantal andere widgets bezit), is het mogelijk om een enkele widget te tonen in zijn eigen window. Widgets zijn niet standaard zichtbaar. De functie "show()":http://doc.qt.nokia.com/4.7/qwidget.html#show zorgt dat ze zichtbaar worden. | ||
Regel 11 zorgt ervoor dat de | Regel 11 zorgt ervoor dat de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html zijn event loop ingaat. Wanneer een Qt applicatie draait worden events gegenereerd en verzonden naar de widgets van de applicatie. Voorbeelden van events zijn muisklikken en toetsaanslagen. Wanneer je text typt in de text edit widget, ontvangt het toetsaanslagevents en reageert dan door de text te tekenen. | ||
Om de applicatie te draaien open je een command prompt en voert de directory in waarin het .cpp bestand van het programma staat. De volgende opdrachten bouwen dan je programma. | Om de applicatie te draaien open je een command prompt en voert de directory in waarin het .cpp bestand van het programma staat. De volgende opdrachten bouwen dan je programma. | ||
Line 42: | Line 42: | ||
|- | |- | ||
|Widgets and Window Geometry | |Widgets and Window Geometry | ||
| | |"Window and Dialog Widgets":http://doc.qt.nokia.com/4.7/application-windows.html | ||
|- | |- | ||
|Events and event handling | |Events and event handling | ||
| | |"The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html | ||
|} | |} | ||
== Afsluitknop toevoegen == | == Afsluitknop toevoegen == | ||
In een echte applicatie heb je normaal gesproken meer dan een widget nodig. We zullen nu de een | In een echte applicatie heb je normaal gesproken meer dan een widget nodig. We zullen nu de een "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html introduceren onder de text edit. De knop zal de kladblok applicatie afsluiten wanneer er op wordt geklikt. | ||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|http://doc.qt.nokia.com/4.7/images/gs2.png]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|http://doc.qt.nokia.com/4.7/images/gs2.png]] | ||
Line 56: | Line 56: | ||
Laten we naar de code kijken. | Laten we naar de code kijken. | ||
<code>#include | <code>#include <QtGui> | ||
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | ||
QTextEdit textEdit;<br /> QPushButton quitButton( | QTextEdit textEdit;<br /> QPushButton quitButton("Quit"); | ||
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | ||
Line 70: | Line 70: | ||
window.show(); | window.show(); | ||
return app.exec | return app.exec();<br />}</code> | ||
Regel 1 includet | Regel 1 includet "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, welke alle GUI classes van Qt bevat. | ||
Regel 10 gebruikt de Signals en Slots mechanismen van Qt om te zorgen dat de applicatie afsluit wanneer op de '''Quit knop''' geklikt wordt. Een slot is een functie die als een programma draait, aangeroepen kan worden via zijn naam (als een string). Een signal is een functie die wanneer hij uitgevoerd wordt de slots zal aanroepen die erbij geregistreerd zijn; dat noemen we het slot verbinden met het signal en het signal uitzenden. | Regel 10 gebruikt de Signals en Slots mechanismen van Qt om te zorgen dat de applicatie afsluit wanneer op de '''Quit knop''' geklikt wordt. Een slot is een functie die als een programma draait, aangeroepen kan worden via zijn naam (als een string). Een signal is een functie die wanneer hij uitgevoerd wordt de slots zal aanroepen die erbij geregistreerd zijn; dat noemen we het slot verbinden met het signal en het signal uitzenden. | ||
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit is een slot van "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html dat de applicatie afsluit. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked is een signal dat "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html uitzendt als erop geklikt wordt. De statische functie "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect zorgt voor het verbinden van het slot met het signal. SIGNAL () en SLOT() zijn twee macros die de zogenaamde function signatures van het signal en het slot die verbonden dienen te worden als parameter nemen. We moeten ook pointers geven aan de objecten die het signal moeten zenden en ontvangen. | |||
Regel 12 maakt een | Regel 12 maakt een "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Zoals eerder besproken kunnen widgets ook een container zijn voor andere widgets. Het is mogelijk om de grenzen (afmeting en positie) van child widgets direct in te stellen, maar het is meestal gemakkelijker om een layout te gebruiken. Een layout beheert de grenzen van de widgets die in een andere widget geplaatst zijn, de zogenaamde kinderen van die container widget. QVBoxLayout, bijvoorbeeld, plaatst de kinderen in een verticale rij onder elkaar. | ||
Regel 13 en 14 voegen het tekst bewerkings vak en de knop toe aan de layout. Met regel 17 plaatsen we de layout in een widget. | Regel 13 en 14 voegen het tekst bewerkings vak en de knop toe aan de layout. Met regel 17 plaatsen we de layout in een widget. | ||
Line 89: | Line 89: | ||
|- | |- | ||
|Signals and slots | |Signals and slots | ||
| | |"Signals & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html | ||
|- | |- | ||
|Layouts | |Layouts | ||
| | |"Layout Management":http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples":http://doc.qt.nokia.com/4.7/examples-layouts.html | ||
|- | |- | ||
|The widgets that come with Qt | |The widgets that come with Qt | ||
| | |"Qt Widget Gallery":http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples":http://doc.qt.nokia.com/4.7/examples-widgets.html | ||
|} | |} | ||
Line 114: | Line 114: | ||
private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};</code> | private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};</code> | ||
De | De "Q_OBJECT":http://doc.qt.nokia.com/4.7/qobject.html#Q_OBJECT macro moet als eerste in de class definitie, het definieert onze class als een "QObject":http://doc.qt.nokia.com/4.7/qobject.html (Dit betekent dat je ook "QObject":http://doc.qt.nokia.com/4.7/qobject.html moet overerven). Een "QObject":http://doc.qt.nokia.com/4.7/qobject.html voegt meerdere extra opties toe aan een normale C++ class. Met name, de class naam en slot namen kunnen tijdens het runnen worden opgevraagd, daarnaast is het mogelijk om de parameters van een slot op te vragen en deze aan te roepen. | ||
Regel 13 definieert het slot quit(). Dit wordt makkelijk gemaakt door de slots macro. Het quit() slot kan nu worden verbonden met signals die dezelfde function signature hebben (ieder signal dat geen parameters heeft). | Regel 13 definieert het slot quit(). Dit wordt makkelijk gemaakt door de slots macro. Het quit() slot kan nu worden verbonden met signals die dezelfde function signature hebben (ieder signal dat geen parameters heeft). | ||
Line 120: | Line 120: | ||
In plaats van het opzetten van de GUI en het verbinden van het slot in de main() functie, maken we nu gebruik van de constructor van Notepad. | In plaats van het opzetten van de GUI en het verbinden van het slot in de main() functie, maken we nu gebruik van de constructor van Notepad. | ||
<code>Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr( | <code>Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr("Quit")); | ||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | ||
QVBoxLayout '''layout = new QVBoxLayout;<br /> layout- | QVBoxLayout '''layout = new QVBoxLayout;<br /> layout->addWidget(textEdit);<br /> layout->addWidget(quitButton); | ||
<br /> setLayout(layout); | <br /> setLayout(layout); | ||
<br /> setWindowTitle(tr( | <br /> setWindowTitle(tr("Notepad"));<br />}</code> | ||
<br />Zoals je als zag in de class definitie, gebruiken we pointers voor onze | <br />Zoals je als zag in de class definitie, gebruiken we pointers voor onze "QObjects":http://doc.qt.nokia.com/4.7/qobject.html (textEdit en quitButton). Als een regel, moet je "QObjects":http://doc.qt.nokia.com/4.7/qobject.html altijd op de heap alloceren en er nooit een kopie van maken. | ||
<br />We maken nu gebruik van de functie | <br />We maken nu gebruik van de functie "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr rond onze zichtbare strings. Deze functie is nodig als je de applicatie in meer dan een taal wil aanbieden (bijvoorbeeld: Engels en Chinees). Hierover zullen we hier niet in meer detail op ingaan, maar je kan de Qt Linguist link van de extra informatie tabel volgen. | ||
<br />h3. Extra informatie<br />|Onderwerp|Hier|<br />|tr() and internationalization| | <br />h3. Extra informatie<br />|Onderwerp|Hier|<br />|tr() and internationalization|"Qt Linguist Manual":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr":http://doc.qt.nokia.com/4.7/linguist-hellotr.html() Example, "Internationalization with Qt":http://doc.qt.nokia.com/4.7/internationalization.html|<br />|QObjects and the Qt Object model (This is essential to understand Qt)|"Object Model":http://doc.qt.nokia.com/4.7/object.html|<br />|qmake and the Qt build system|"qmake Manual":http://doc.qt.nokia.com/4.7/qmake-manual.html| | ||
<br />h3. Aanmaken van een .pro bestand | <br />h3. Aanmaken van een .pro bestand | ||
<br />Voor dit voorbeeld maken we ons eigen .pro bestand, in plaats van gebruik te maken van de optie | <br />Voor dit voorbeeld maken we ons eigen .pro bestand, in plaats van gebruik te maken van de optie -project van qmake. | ||
<br /><code>HEADERS = notepad.h<br />SOURCES = notepad.cpp main.cpp</code> | <br /><code>HEADERS = notepad.h<br />SOURCES = notepad.cpp main.cpp</code> | ||
<br />De volgende opdrachten bouwen dan het voorbeeld. | <br />De volgende opdrachten bouwen dan het voorbeeld. | ||
<br /><code>qmake<br />make</code> | <br /><code>qmake<br />make</code> | ||
<br />h2. Gebruik maken van QMainWindow | <br />h2. Gebruik maken van QMainWindow | ||
<br />Veel applicaties zullen profiteren van het gebruik van een | <br />Veel applicaties zullen profiteren van het gebruik van een "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, welke zijn eigen layout heeft waaraan je bijvoorbeeld een menu balk, dock widgets, tool balken, en een status balk kan toevoegen. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html heeft een centrum gebied dat gebruikt kan worden voor ieder type widget. In ons geval zullen we daar ons text edit plaatsen. | ||
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|http://doc.qt.nokia.com/4.7/images/gs4.png]] | <br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|http://doc.qt.nokia.com/4.7/images/gs4.png]] | ||
<br />Laten we kijken naar de class definitie van Notepad. | <br />Laten we kijken naar de class definitie van Notepad. | ||
<br /><code>#include | <br /><code>#include <QtGui> | ||
<br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT | <br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT | ||
<br />public:<br /> Notepad(); | <br />public:<br /> Notepad(); | ||
Line 147: | Line 147: | ||
<br /> QMenu '''fileMenu;<br />};</code> | <br /> QMenu '''fileMenu;<br />};</code> | ||
<br />We includen nog 2 slots die documenten kunnen openen en opslaan. Deze zullen in de volgende sectie implementeren. | <br />We includen nog 2 slots die documenten kunnen openen en opslaan. Deze zullen in de volgende sectie implementeren. | ||
<br />In een main window moet hetzelfde slot vaak door meerdere widgets worden aangeroepen. Voorbeelden hiervan zijn menu items en knoppen op een tool bar. Om dit makkelijker te maken heeft Qt | <br />In een main window moet hetzelfde slot vaak door meerdere widgets worden aangeroepen. Voorbeelden hiervan zijn menu items en knoppen op een tool bar. Om dit makkelijker te maken heeft Qt "QAction":http://doc.qt.nokia.com/4.7/qaction.html, welke aan meerdere widgets meegegeven kan worden en verbonden kan worden aan een slot. Zowel een "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html als een "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html kunnen bijvoorbeeld menu items en tool buttons maken van dezelfde "QActions":http://doc.qt.nokia.com/4.7/qaction.html. We zullen zo zien hoe dit werkt. | ||
<br />Net als de vorige keer, gebruiken we de constructor van Notepad voor het aanmaken van de GUI. | <br />Net als de vorige keer, gebruiken we de constructor van Notepad voor het aanmaken van de GUI. | ||
<br /><code>Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr( | <br /><code>Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr("&Open"), this);<br /> saveAction = new QAction(tr("&Save"), this);<br /> exitAction = new QAction(tr("E&amp;xit"), this); | ||
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | <br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | ||
<br /> fileMenu = menuBar() | <br /> fileMenu = menuBar()->addMenu(tr("&File"));<br /> fileMenu->addAction(openAction);<br /> fileMenu->addAction(saveAction);<br /> fileMenu->addSeparator();<br /> fileMenu->addAction(exitAction); | ||
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit); | <br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit); | ||
<br /> setWindowTitle(tr( | <br /> setWindowTitle(tr("Notepad"));<br />}</code> | ||
<br /> | <br />"QActions":http://doc.qt.nokia.com/4.7/qaction.html worden aangemaakt met de text die zichtbaar moet zijn op de widgets waar we ze aan toevoegen (in ons geval, menu items). Als we ze ook aan een tool bar wilden toevoegen, zouden we een "icon":http://doc.qt.nokia.com/4.7/qicon.html kunnen meegeven aan de actions. | ||
<br />Wanneer er op een menu item word geklikt, zal dit de action triggeren, en het bijbehorende slot zal worden aangeroepen. | <br />Wanneer er op een menu item word geklikt, zal dit de action triggeren, en het bijbehorende slot zal worden aangeroepen. | ||
<br />h3. Extra informatie<br />|Onderwerp|Hier|<br />|Main windows and main window classes| | <br />h3. Extra informatie<br />|Onderwerp|Hier|<br />|Main windows and main window classes|"Application Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples":http://doc.qt.nokia.com/4.7/examples-mainwindow.html|<br />|MDI applications|"QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html| | ||
<br />h2. Opslaan en laden | <br />h2. Opslaan en laden | ||
<br />In dit voorbeeld zullen we de functionaliteit van de open() en save() slots, die we in het vorige voorbeeld hebben toegevoegd, implementeren. | <br />In dit voorbeeld zullen we de functionaliteit van de open() en save() slots, die we in het vorige voorbeeld hebben toegevoegd, implementeren. | ||
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|http://doc.qt.nokia.com/4.7/images/gs5.png]] | <br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|http://doc.qt.nokia.com/4.7/images/gs5.png]] | ||
<br />We zullen beginnen met het open() slot: | <br />We zullen beginnen met het open() slot: | ||
<br /><code>QString fileName = QFileDialog::getOpenFileName(this, tr( | <br /><code>QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)")); | ||
<br />if (fileName != | <br />if (fileName != "") {<br /> QFile file(fileName);<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr("Error"),<br /> tr("Could not open file"));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit->setPlainText(contents);<br /> file.close();<br />}</code> | ||
<br />De eerst stap is om aan de gebruiker de naam van het bestand dat geopend moet worden te vragen. Qt heeft een | <br />De eerst stap is om aan de gebruiker de naam van het bestand dat geopend moet worden te vragen. Qt heeft een "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, welke een dialog is waarin de gebruiker een bestand kan selecteren. Het plaatje hierboven toont dit dialog in Kubuntu. De static "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName functie toont een modal file dialog, en keert niet terug totdat de gebruiker een file heeft geselecteerd. Het geeft de bestands locatie van het bestand dat is geselecteerd terug, of een lege string wanneer de gebruiker op cancel heeft gedrukt. | ||
<br />Als we eenmaal een bestands naam hebben, proberen we dit bestand te openen met | <br />Als we eenmaal een bestands naam hebben, proberen we dit bestand te openen met "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, welke true terug geeft als het bestand geopend kon worden. We zullen niet ingaan op de error afhandeling, maar je kan daarvoor de links in het extra informatie deel volgen. Als het bestand niet kon worden geopend, gebruiken we "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html om een dialog te tonen met daarin het error bericht (bekijk de "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html class beschrijving voor meer informatie). | ||
<br />Het lezen van data is eigenlijk heel triviaal door middel van de | <br />Het lezen van data is eigenlijk heel triviaal door middel van de "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll functie, welke alle data in het bestand teruggeeft als een "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. De "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData geeft alle data terug als een array van const char''', waar QString een constructor voor heeft. De inhoud kan dan worden getoond in de text edit. We sluiten dan het bestand af met "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close om de file descriptor terug te geven aan het besturings systeem. | ||
Laten we nu kijken naar de implementatie van het save() slot. | Laten we nu kijken naar de implementatie van het save() slot. | ||
<code>QString fileName = QFileDialog::getSaveFileName(this, tr( | <code>QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)")); | ||
<br />if (fileName != | <br />if (fileName != "") {<br /> QFile file(fileName);<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&file);<br /> stream << textEdit->toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br />}</code> | ||
<br />We schrijven de inhoud van de text edit naar het bestand naar welke word gewezen in het | <br />We schrijven de inhoud van de text edit naar het bestand naar welke word gewezen in het "QFile":http://doc.qt.nokia.com/4.7/qfile.html object, hiervoor gebruiken we de "QTextStram":http://doc.qt.nokia.com/4.7/qtextstream.html class. De text stream kan een "QString":http://doc.qt.nokia.com/4.7/qstring.html direct naar het bestand schrijven; "QFile":http://doc.qt.nokia.com/4.7/qfile.html accepteert alleen ruwe data (char''') met de "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write functies van het "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html. | ||
=== Extra informatie<br />|Onderwerp|Hier| === | === Extra informatie<br />|Onderwerp|Hier| === |
Revision as of 14:17, 24 February 2015
[toc align_right="yes" depth="3"]
Beginnen met programmeren in Qt
Welkom in de wereld van Qt — de cross-platform GUI toolkit. In deze "getting started guide" zullen we u basis Qt kennis bijbrengen door een simpele kladblok applicatie te maken. Na het lezen van deze oefening, zult u klaar zijn om in onze overzichten en API documentatie te duiken, en alle informatie te vinden die u nodig heeft voor de applicatie die u ontwikkelt.
Hallo Kladblok
In dit eerste voorbeeld zullen we een eenvoudig venster op de desktop maken met daarin een text edit. Dit representeert het simpelste Qt programma met een GUI.
p=. http://doc.qt.nokia.com/4.7/images/gs1.png
Hier is de code:
#include <QApplication><br />#include <QTextEdit>
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
QTextEdit textEdit;<br /> textEdit.show();
return app.exec();<br />}
Laten we dit stuk code regel voor regel doornemen. In de eerste twee regels includen we de header files voor "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html en "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, die de twee classes zijn die we voor dit voorbeeld nodig hebben. Alle Qt classes hebben een header met zelfde naam.
Regel 6 creëert een "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html object. Dit object beheert alle resources die nodig zijn voor een Qt applicatie met een GUI. Het heeft argv en args nodig omdat Qt applicaties enkele command line argumenten accepteren.
Regel 8 creert een "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html object. Een text edit is een visueel element in de GUI. In Qt noemen we dit soort elementen widgets. Voorbeelden van andere widgets zijn scroll bars, labels en radio knoppen. Een widget can ook een container zijn voor andere widgets, een dialog of een main applicatie bijvoorbeeld.
Regel 9 toont de text edit op het scherm in zijn eigen window frame. Omdat widgets ook als containers functioneren (bijvoorbeeld een "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, die toolbars, menus, een status bar, en een aantal andere widgets bezit), is het mogelijk om een enkele widget te tonen in zijn eigen window. Widgets zijn niet standaard zichtbaar. De functie "show()":http://doc.qt.nokia.com/4.7/qwidget.html#show zorgt dat ze zichtbaar worden.
Regel 11 zorgt ervoor dat de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html zijn event loop ingaat. Wanneer een Qt applicatie draait worden events gegenereerd en verzonden naar de widgets van de applicatie. Voorbeelden van events zijn muisklikken en toetsaanslagen. Wanneer je text typt in de text edit widget, ontvangt het toetsaanslagevents en reageert dan door de text te tekenen.
Om de applicatie te draaien open je een command prompt en voert de directory in waarin het .cpp bestand van het programma staat. De volgende opdrachten bouwen dan je programma.
qmake -project<br />qmake<br />make
Dit laat een executable achter in de part1 map (onthoud dat op Windows je mogelijk gebruik moet maken van nmake in plaats van make. Daarnaast word de executable in de map part1/debug of part1/release geplaatst). qmake is Qt's build applicatie dat een configuratie bestand accepteert. qmake genereert dit voor ons wanneer het argument -project word meegegeven. Aan de hand van het configuratie bestand (eindigend met .pro) produceert qmake een Makefile dat je programma voor je zal bouwen. We zullen later kijken naar hoe we zelf een .pro kunnen schrijven.
Extra informatie
Onderwerp | Hier |
Widgets and Window Geometry | "Window and Dialog Widgets":http://doc.qt.nokia.com/4.7/application-windows.html |
Events and event handling | "The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html |
Afsluitknop toevoegen
In een echte applicatie heb je normaal gesproken meer dan een widget nodig. We zullen nu de een "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html introduceren onder de text edit. De knop zal de kladblok applicatie afsluiten wanneer er op wordt geklikt.
p=. http://doc.qt.nokia.com/4.7/images/gs2.png
Laten we naar de code kijken.
#include <QtGui>
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
QTextEdit textEdit;<br /> QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout layout;<br /> layout.addWidget(&textEdit);<br /> layout.addWidget(&quitButton);
QWidget window;<br /> window.setLayout(&layout);
window.show();
return app.exec();<br />}
Regel 1 includet "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, welke alle GUI classes van Qt bevat.
Regel 10 gebruikt de Signals en Slots mechanismen van Qt om te zorgen dat de applicatie afsluit wanneer op de Quit knop geklikt wordt. Een slot is een functie die als een programma draait, aangeroepen kan worden via zijn naam (als een string). Een signal is een functie die wanneer hij uitgevoerd wordt de slots zal aanroepen die erbij geregistreerd zijn; dat noemen we het slot verbinden met het signal en het signal uitzenden.
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit is een slot van "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html dat de applicatie afsluit. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked is een signal dat "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html uitzendt als erop geklikt wordt. De statische functie "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect zorgt voor het verbinden van het slot met het signal. SIGNAL () en SLOT() zijn twee macros die de zogenaamde function signatures van het signal en het slot die verbonden dienen te worden als parameter nemen. We moeten ook pointers geven aan de objecten die het signal moeten zenden en ontvangen.
Regel 12 maakt een "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Zoals eerder besproken kunnen widgets ook een container zijn voor andere widgets. Het is mogelijk om de grenzen (afmeting en positie) van child widgets direct in te stellen, maar het is meestal gemakkelijker om een layout te gebruiken. Een layout beheert de grenzen van de widgets die in een andere widget geplaatst zijn, de zogenaamde kinderen van die container widget. QVBoxLayout, bijvoorbeeld, plaatst de kinderen in een verticale rij onder elkaar.
Regel 13 en 14 voegen het tekst bewerkings vak en de knop toe aan de layout. Met regel 17 plaatsen we de layout in een widget.
Extra informatie
Onderwerp | Hier |
Signals and slots | "Signals & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html |
Layouts | "Layout Management":http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples":http://doc.qt.nokia.com/4.7/examples-layouts.html |
The widgets that come with Qt | "Qt Widget Gallery":http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples":http://doc.qt.nokia.com/4.7/examples-widgets.html |
Subklasse van QWidget
Het kan zijn dat als de gebruiker de applicatie afsluit je een dialoogscherm wil tonen met de vraag of hij/zij de applicatie echt wil afsluiten. In dit voorbeeld leiden we een klasse af van QWidget, en we voegen een slot toe dat we met de Quit knop verbinden.
p=. http://doc.qt.nokia.com/4.7/images/gs3.png
Laten we naar de code kijken:
class Notepad : public QWidget<br />{<br /> Q_OBJECT
public:<br /> Notepad();
private slots:<br /> void quit();
private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};
De "Q_OBJECT":http://doc.qt.nokia.com/4.7/qobject.html#Q_OBJECT macro moet als eerste in de class definitie, het definieert onze class als een "QObject":http://doc.qt.nokia.com/4.7/qobject.html (Dit betekent dat je ook "QObject":http://doc.qt.nokia.com/4.7/qobject.html moet overerven). Een "QObject":http://doc.qt.nokia.com/4.7/qobject.html voegt meerdere extra opties toe aan een normale C++ class. Met name, de class naam en slot namen kunnen tijdens het runnen worden opgevraagd, daarnaast is het mogelijk om de parameters van een slot op te vragen en deze aan te roepen.
Regel 13 definieert het slot quit(). Dit wordt makkelijk gemaakt door de slots macro. Het quit() slot kan nu worden verbonden met signals die dezelfde function signature hebben (ieder signal dat geen parameters heeft).
In plaats van het opzetten van de GUI en het verbinden van het slot in de main() functie, maken we nu gebruik van de constructor van Notepad.
Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr("Quit"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout '''layout = new QVBoxLayout;<br /> layout->addWidget(textEdit);<br /> layout->addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr("Notepad"));<br />}
Zoals je als zag in de class definitie, gebruiken we pointers voor onze "QObjects":http://doc.qt.nokia.com/4.7/qobject.html (textEdit en quitButton). Als een regel, moet je "QObjects":http://doc.qt.nokia.com/4.7/qobject.html altijd op de heap alloceren en er nooit een kopie van maken.
We maken nu gebruik van de functie "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr rond onze zichtbare strings. Deze functie is nodig als je de applicatie in meer dan een taal wil aanbieden (bijvoorbeeld: Engels en Chinees). Hierover zullen we hier niet in meer detail op ingaan, maar je kan de Qt Linguist link van de extra informatie tabel volgen.
h3. Extra informatie
|Onderwerp|Hier|
|tr() and internationalization|"Qt Linguist Manual":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr":http://doc.qt.nokia.com/4.7/linguist-hellotr.html() Example, "Internationalization with Qt":http://doc.qt.nokia.com/4.7/internationalization.html%7C
|QObjects and the Qt Object model (This is essential to understand Qt)|"Object Model":http://doc.qt.nokia.com/4.7/object.html%7C
|qmake and the Qt build system|"qmake Manual":http://doc.qt.nokia.com/4.7/qmake-manual.html%7C
h3. Aanmaken van een .pro bestand
Voor dit voorbeeld maken we ons eigen .pro bestand, in plaats van gebruik te maken van de optie -project van qmake.
HEADERS = notepad.h<br />SOURCES = notepad.cpp main.cpp
De volgende opdrachten bouwen dan het voorbeeld.
qmake<br />make
h2. Gebruik maken van QMainWindow
Veel applicaties zullen profiteren van het gebruik van een "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, welke zijn eigen layout heeft waaraan je bijvoorbeeld een menu balk, dock widgets, tool balken, en een status balk kan toevoegen. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html heeft een centrum gebied dat gebruikt kan worden voor ieder type widget. In ons geval zullen we daar ons text edit plaatsen.
p=. http://doc.qt.nokia.com/4.7/images/gs4.png
Laten we kijken naar de class definitie van Notepad.
#include <QtGui>
<br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT
<br />public:<br /> Notepad();
<br />private slots:<br /> void open();<br /> void save();<br /> void quit();
<br />private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br />};
We includen nog 2 slots die documenten kunnen openen en opslaan. Deze zullen in de volgende sectie implementeren.
In een main window moet hetzelfde slot vaak door meerdere widgets worden aangeroepen. Voorbeelden hiervan zijn menu items en knoppen op een tool bar. Om dit makkelijker te maken heeft Qt "QAction":http://doc.qt.nokia.com/4.7/qaction.html, welke aan meerdere widgets meegegeven kan worden en verbonden kan worden aan een slot. Zowel een "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html als een "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html kunnen bijvoorbeeld menu items en tool buttons maken van dezelfde "QActions":http://doc.qt.nokia.com/4.7/qaction.html. We zullen zo zien hoe dit werkt.
Net als de vorige keer, gebruiken we de constructor van Notepad voor het aanmaken van de GUI.
Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr("&Open"), this);<br /> saveAction = new QAction(tr("&Save"), this);<br /> exitAction = new QAction(tr("E&amp;xit"), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()->addMenu(tr("&File"));<br /> fileMenu->addAction(openAction);<br /> fileMenu->addAction(saveAction);<br /> fileMenu->addSeparator();<br /> fileMenu->addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr("Notepad"));<br />}
"QActions":http://doc.qt.nokia.com/4.7/qaction.html worden aangemaakt met de text die zichtbaar moet zijn op de widgets waar we ze aan toevoegen (in ons geval, menu items). Als we ze ook aan een tool bar wilden toevoegen, zouden we een "icon":http://doc.qt.nokia.com/4.7/qicon.html kunnen meegeven aan de actions.
Wanneer er op een menu item word geklikt, zal dit de action triggeren, en het bijbehorende slot zal worden aangeroepen.
h3. Extra informatie
|Onderwerp|Hier|
|Main windows and main window classes|"Application Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples":http://doc.qt.nokia.com/4.7/examples-mainwindow.html%7C
|MDI applications|"QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html%7C
h2. Opslaan en laden
In dit voorbeeld zullen we de functionaliteit van de open() en save() slots, die we in het vorige voorbeeld hebben toegevoegd, implementeren.
p=. http://doc.qt.nokia.com/4.7/images/gs5.png
We zullen beginnen met het open() slot:
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)"));
<br />if (fileName != "") {<br /> QFile file(fileName);<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr("Error"),<br /> tr("Could not open file"));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit->setPlainText(contents);<br /> file.close();<br />}
De eerst stap is om aan de gebruiker de naam van het bestand dat geopend moet worden te vragen. Qt heeft een "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, welke een dialog is waarin de gebruiker een bestand kan selecteren. Het plaatje hierboven toont dit dialog in Kubuntu. De static "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName functie toont een modal file dialog, en keert niet terug totdat de gebruiker een file heeft geselecteerd. Het geeft de bestands locatie van het bestand dat is geselecteerd terug, of een lege string wanneer de gebruiker op cancel heeft gedrukt.
Als we eenmaal een bestands naam hebben, proberen we dit bestand te openen met "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, welke true terug geeft als het bestand geopend kon worden. We zullen niet ingaan op de error afhandeling, maar je kan daarvoor de links in het extra informatie deel volgen. Als het bestand niet kon worden geopend, gebruiken we "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html om een dialog te tonen met daarin het error bericht (bekijk de "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html class beschrijving voor meer informatie).
Het lezen van data is eigenlijk heel triviaal door middel van de "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll functie, welke alle data in het bestand teruggeeft als een "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. De "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData geeft alle data terug als een array van const char, waar QString een constructor voor heeft. De inhoud kan dan worden getoond in de text edit. We sluiten dan het bestand af met "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close om de file descriptor terug te geven aan het besturings systeem.
Laten we nu kijken naar de implementatie van het save() slot.
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));
<br />if (fileName != "") {<br /> QFile file(fileName);<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&file);<br /> stream << textEdit->toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br />}
We schrijven de inhoud van de text edit naar het bestand naar welke word gewezen in het "QFile":http://doc.qt.nokia.com/4.7/qfile.html object, hiervoor gebruiken we de "QTextStram":http://doc.qt.nokia.com/4.7/qtextstream.html class. De text stream kan een "QString":http://doc.qt.nokia.com/4.7/qstring.html direct naar het bestand schrijven; "QFile":http://doc.qt.nokia.com/4.7/qfile.html accepteert alleen ruwe data (char) met de "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write functies van het "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html.