Basic Programming/hu: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
'''Magyar''' | [[Category:Learning]][[Category:Hungarian]]<br />'''Magyar''' | ||
=Bevezetés a Qt programozás alapjaiba= | = Bevezetés a Qt programozás alapjaiba = | ||
Üdvözöllek a Qt keresztplatformos fejlesztői rendszer világában. Ebben a leírásban egy egyszerű jegyzettömb alkalmazás elkészítése során bemutatjuk a Qt programozás alapfogásait. Az útmutató tanulmányozása során nyugodtan nézz bele az | Üdvözöllek a Qt keresztplatformos fejlesztői rendszer világában. Ebben a leírásban egy egyszerű jegyzettömb alkalmazás elkészítése során bemutatjuk a Qt programozás alapfogásait. Az útmutató tanulmányozása során nyugodtan nézz bele az API dokumentációba, amennyiben valamivel kapcsolatban több információra van szükséged. | ||
Az útmutató angol nyelvű változata elérhető az http://doc.qt.nokia.com/gettingstartedqt.html | Az útmutató angol nyelvű változata elérhető az "http://doc.qt.nokia.com/gettingstartedqt.html&quot;:http://doc.qt.nokia.com/gettingstartedqt.html oldalon. | ||
==Hello Jegyzettömb== | == Hello Jegyzettömb == | ||
Példánkban egy egyszerű szövegdobozt hozunk létre egy ablakkeretben. Ez lesz a legegyszerűbb felhasználói felülettel rendelkező Qt segítségével írt program. | Példánkban egy egyszerű szövegdobozt hozunk létre egy ablakkeretben. Ez lesz a legegyszerűbb felhasználói felülettel rendelkező Qt segítségével írt program. | ||
[[Image:gs1.png|Notepad]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Notepad]] | ||
Íme a kód:<br /> | Íme a kód:<br /><code>#include <QApplication&gt;<br />#include <QTextEdit&gt; | ||
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | |||
QTextEdit textEdit;<br /> textEdit.show(); | |||
return app.exec&amp;#40;&#41;;<br />}</code> | |||
Vizsgáljuk meg a kódot sorról sorra. Az első két sorban a "QApplication&quot;:http://doc.qt.nokia.com/qapplication.html és a "QTextEdit&quot;:http://doc.qt.nokia.com/qtextedit.html osztály használatához szükséges headerfájlokat includoljuk be a programunkba. A Qt összes osztályának megvan a nevével megegyező headerje. | |||
A | A 6. sorban létrehozunk egy "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html objektumot. Ez az objektum kezeli az alkalmazás összes erőforrását. Egy ilyen objektum létrehozása szükséges minden grafikus Qt alkalmazáshoz. Argumentumként át kell adni az argv és args paramétereket, mivel a Qt-ban írt alkalmazásoknak "van néhány beépített parancssori argumentuma&quot;:http://doc.trolltech.com/4.7/qapplication.html#QApplication. | ||
A 8. sorban létrehozunk egy "QTextEdit&quot;:http://doc.qt.nokia.com/qtextedit.html objektumot. Ez a szövegdoboz egy megjeleníthető grafikus elem. A Qt-ban az ilyeneket widgeteknek hívjuk. További widgetek például: gördítősávok, címkék, rádiógombok. Minden widget lehet egyfajta konténer további widgetek számára, mint például egy ablak, vagy egy dialógus. | |||
A 9. sorban megjelenítjük a szövegdobozt a saját ablakkeretében. Mint már említettem, a widgetek konténerként is funkcionálnak mint például a "QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html, amelynek van menüsora, státuszsora, és még néhány egyéb beépített widgete. Továbbá lehetőség van egyetlen widget megjelenítésére is főablakba helyezés nélkül, ez esetben maga a widget kap egy ablakkeretet. A widgetek alapból nem láthatóak, a show() metódus meghívása teszi őket azzá. | |||
A 11. sorban meghívjuk a "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html eseménykezelő rutinját. Ha egy Qt alkalmazás futása közben esemény történik, akkor az kiküldődik a megfelelő widgethez. Például az egérkattintás és a billentyűleütések esetében a szövegdobozunk fogja megkapni ezeket az eseményeket. Az ilyen és ehhez hasonló feladatokat intézi ez a metódus. | |||
Az alakalmazás fordításához és futtatásához nyiss meg egy parancssort, lépj be abba a mappában, ahol a .cpp fájlod található, és futtasd le a következő parancsokat: | |||
<code><br /> qmake -project<br /> qmake<br /> make<br /></code> | |||
[[Image:gs2.png|Eingabefeld mit Beenden Knopf]] | Ezen műveletek után egy futtatható binárisnak kell megjelennie a part1 mappában. (Megjegyzés a Windowst és VisualStudiot használóknak: a make nmaket kell futtatniuk, továbbá a bináris a part1/debug vagy part1/release mappában fog létrejönni.)<br />A qmake a Qt build eszköze ami argumentum nélkül egy projekt fájlt keres, amit fel tud dolgozni. A <s>project argumentummal létrehoz automatikusan egy .pro fájlt a mappában található fájlokat hozzáadva. A qmaket futtatva létrejön a Makefile, amit a make programod fog feldolgozni. A .pro fájlok írásáról később még lesz szó. Amennyiben Windows alatt valamit hiányolna a fordítás során, akkor keresd ki a start menüből a Qt Command prompt-ot, és abból futtasd a parancsokat. | ||
<br />h3. További olvasnivalók:<br />|''. Miről |''. Hol |<br />| Widgetek és ablakok geometriája | "Window and Dialog Widgets&quot;:http://doc.qt.nokia.com/4.7/application-windows.html |<br />| Események és a Qt eseménykezelője | "The Event System&quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html | | |||
<br />h2. Kilépés gomb hozzáadása | |||
<br />Egy igazi alkalmazásban általában egynél több widgetre van szükséged. Helyezzünk egy "QPushButtont&quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html a szövegdoboz alá. Ez arra fog szolgálni, hogy ha a felhasználó rákattint, a program lépjen ki. | |||
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Eingabefeld mit Beenden Knopf]] | |||
<br />Nézzük a kódot: | |||
<br /><code><br />#include <QtGui&gt; | |||
<br />int main(int argv, char **args)<br />{<br /> QApplication app(argv, args); | |||
<br /> QTextEdit textEdit;<br /> QPushButton quitButton("Quit&quot;); | |||
<br /> QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | |||
<br /> QVBoxLayout layout;<br /> layout.addWidget(&textEdit);<br /> layout.addWidget(&quitButton); | |||
<br /> QWidget window;<br /> window.setLayout(&layout); | |||
<br /> window.show(); | |||
<br /> return app.exec&amp;#40;&#41;;<br />}<br /></code> | |||
<br />Az első sorban beincludoljuk a "QtGui&quot;:http://doc.qt.nokia.com/4.7/qtgui.html headert, ami magában foglalja a Qt összes grafikus osztályát. | |||
<br />A tizedik sorban a Qt szignál slot mechanizmusa segítségével lekezeljük a Kilépés gomb megnyomását. | |||
<br />A szlot függvény a futás során hívódik meg a neve segítségével. A szignálok olyan függvények, amelyek a megfelelő esemény bekövetkezésekor automatikusan meghívják a hozzájuk csatlakoztatott slotokat. Esetünkben a "quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit a widgetünk egy beépített slotja, amelyet meghívva az alkalmazás kilép. A gombunk "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked szignálja pedig a gomb megnyomásakor emittálódik. A szignál-slot hozzárendelést a statikus "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html# függvénnyel hozhatjuk létre. Az argumentumként használt SIGNAL () és SLOT() makrókban kell megadnunk a megfelelő függvényneveket, azok argumentumainak típusával egyetemben. A connect() függvénynek át kell adni a küldő és fogadó objektumokra mutató mutatókat is. | |||
<br />A 12. sorban egy "QVBoxLayout-ot&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html hozunk létre. Ahogy már említettük a widgetek (szülő widget) tartalmazhatnak további widgeteket (gyermek widgetek). Lehetőségünk van a gyermek widgeteknek pontos méretet, pozíciót megadni, de egyszerűbb, ha ehelyett layoutokat használunk, így a azok fogják kezelni a gyermekwidgetek elrendezését. A "QVBoxLayout&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html például a gyermekeket egy függőleges oszlopba rendezi. | |||
<br />A 13. és 14. sorban hozzáadjuk a szövegdobozunkat és a nyomógombunkat a layouthoz, majd a 17. sorban érvénybe léptetjük az elrendezést. | |||
<br />h3. További olvasnivalók:<br />|''. Miről |''. Hol |<br />| Szignálok és Szlotok | "Signals & Slots&quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html |<br />| Layoutok | "Layout Management&quot;:http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts&quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples&quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html |<br />| A QT beépített widgetkészlete | "Qt Widget Gallery&quot;:http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples&quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html | | |||
<br />h2. Származtatás a QWidget osztályból | |||
<br />Miután a felhasználó a kilépés gombra kattint, sok esetben érdemes egy megerősítést kérő ablakot megjeleníteni, hogy valóban ki akar-e lépni. Példánkban a "QWidget&quot;:http://doc.qt.nokia.com/4.7/qwidget.html osztályból származtatjuk a programfelület legfelsőbbb osztályát, és létrehozunk egy slotot, amihez hozzákötjük a Kilépés gomb kattintás szignálját. | |||
<br />Íme a kód: | |||
<br /><code><br /> class Notepad : public QWidget<br /> {<br /> Q_OBJECT | |||
<br /> public:<br /> Notepad(); | |||
<br /> private slots:<br /> void quit(); | |||
<br /> private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br /> };<br /></code> | |||
<br />A Q_OBJECT makrónak kell az osztálydeklaráció elején lennie. Ez a makró az osztályunkat "QObjectként&quot;:http://doc.qt.nokia.com/4.7/qobject.html deklarálja (természetesen a használatához a "QObjecttől&quot;:http://doc.qt.nokia.com/4.7/qobject.html kell származtatnunk). Ez a példánkban is így van, hiszen a QWidget osztály a QObjectből van származtatva. A "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html különféle funkciókkal bővíti ki a C++ osztályok tulajdonságait. Például az osztály és szlotok neve lekérdezhetővé válik futásidőben. Továbbá lehetőség van a szlotok argumentumainak típusát lekérdezni, illetve név alapján meghívni azokat. | |||
<br />A 9. sorban deklaráljuk a quit() szlotot a '''slots''' makró segítségével. A slotunkat ezután hozzáköthetjük bármilyen szignálhoz, amelynek nincs argumentuma. | |||
<br />A következőekben létrehozunk egy Notepad osztályt, amelynek a konstruktorában hozzuk létre a felületet, és kötjük össze a slotokat a szignálokkal. Ez megoldás elegánsabb, mint ha ezt a main() függvényben tennénk meg. | |||
<br /><code><br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr("Quit&quot;)); | |||
<br /> connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | |||
<br /> QVBoxLayout *layout = new QVBoxLayout;<br /> layout</s>>addWidget(textEdit);<br /> layout->addWidget(quitButton); | |||
setLayout(layout); | |||
setWindowTitle(tr("Notepad&quot;));<br /> }<br /></code> | |||
Amint láthatod mutatókat használunka textEdit és a quitButton elérésére. Az ilyen grafikus elemeket mindig a heapen példányosítjuk, és sohasem másoljuk őket. | Amint láthatod mutatókat használunka textEdit és a quitButton elérésére. Az ilyen grafikus elemeket mindig a heapen példányosítjuk, és sohasem másoljuk őket. | ||
Az ablak címét a setWindowTitle metódus segítségével állítjuk be. Amint láthatod a felhasználó számára látható szöveget a | Az ablak címét a setWindowTitle metódus segítségével állítjuk be. Amint láthatod a felhasználó számára látható szöveget a "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr függvényen keresztül adjuk át a függvénynek. Ez a függvény a többnyelvű alkalmazások írásánál nyújt segítséget. Most nem megyünk bele a részletekbe, további információt a "Qt Linguist&quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html dokumentációjánál találsz. | ||
===További olvasnivalók: | === További olvasnivalók:<br />|''. Miről |''. Hol |<br />| tr() és a többnyelvűsítés | "Qt Linguist Manual&quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation&quot;: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&quot;:http://doc.qt.nokia.com/4.7/internationalization.html |<br />| "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html és a Qt objektummodell-rendszere | "Object Model&quot;:http://doc.qt.nokia.com/4.7/object.html |<br />| qmake a Qt build rendszere | "qmake Manual&quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html | === | ||
Az elkövetkezőkben írunk egy saját .pro fájlt, ahelyett, hogy a qmake-el generáltatnánk le. | Az elkövetkezőkben írunk egy saját .pro fájlt, ahelyett, hogy a qmake-el generáltatnánk le. | ||
<code> HEADERS = notepad.h<br /> SOURCES = notepad.cpp main.cpp</code> | |||
A következő parancsokkal tudod lefordítani a példát: | A következő parancsokkal tudod lefordítani a példát: | ||
=A QMainWindow használata= | <code> qmake<br /> make</code> | ||
= A QMainWindow használata = | |||
Sok alkalmazás írásakor kézenfekvő lehet a használata, ugyanis ez az osztály egy előre megadott layout-ot tartalmaz, amelyre elhelyezhetjük saját menü sorunkat, eszköztárainkat, a dokkolható widgetek számára rögzítési területet, illetve az állapotsort is. <br /> A | Sok alkalmazás írásakor kézenfekvő lehet a használata, ugyanis ez az osztály egy előre megadott layout-ot tartalmaz, amelyre elhelyezhetjük saját menü sorunkat, eszköztárainkat, a dokkolható widgetek számára rögzítési területet, illetve az állapotsort is.<br />A "QMainWindownak&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html van egy középső területe, ahol elhelyezhetünk bármilyen widgetet. Esetünkben is ide fog kerülni a szövegdobozunk. | ||
[[Image:gs4.png|QMainWindow]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|QMainWindow]] | ||
Tekintsük át a Notepad osztály definícióját! | Tekintsük át a Notepad osztály definícióját! | ||
<code><br /> #include <QtGui&gt; | |||
class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT | |||
public:<br /> Notepad(); | |||
private slots:<br /> void open();<br /> void save();<br /> void quit(); | |||
private:<br /> QTextEdit *textEdit; | |||
QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction; | |||
QMenu '''fileMenu;<br /> };<br /></code> | |||
<br />Az elkövetkezendőkben implementálni fogunk két slotot, mely a dokumentum megnyitására és mentésére fog szolgálni. | |||
<br />A fő ablakokban gyakran megesik az, hogy egy szlotot több widget is meghív. Esetünkben a menü egyes elemei és az eszköztár gombjai is ezt teszik. Az ilyen esetek leegyszerűsítésére hozták létre a "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html osztályt, amelyet átadhatunk több widgetnek is, majd hozzákötjük a megfelelő szlothoz a szignálját. Például a "QMenu&quot;:http://doc.qt.nokia.com/4.7/qmenu.html és a "QToolBar&quot;:http://doc.qt.nokia.com/4.7/qtoolbar.html is létrehozhat menüket, eszköztárelemeket ugyanannak a "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html <s>nek a hatására. | |||
<br />Ahogyan már említettük a grafikus elemeket a Notepad osztály konstruktorában inicializáljuk. | |||
<br /><code><br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr("&Open&quot;), this);<br /> saveAction = new QAction(tr("&Save&quot;), this);<br /> exitAction = new QAction(tr("E&amp;xit&quot;), 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()</s>>addMenu(tr("&File&quot;));<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&quot;));<br /> }<br /></code> | |||
<br />A "QAction-ök&quot;:http://doc.qt.nokia.com/4.7/qaction.html konstruktorának egy szöveget adunk meg argumentumként. Ez a szöveg fog megjelenni azokon a widgeteken, amelyekhez hozzárendeljük őket (esetünkben a menüelemeken). Ha ugyanazt a funkciót el szeretnénk érni az eszköztárunkról is, akkor az akcióhoz ikont is kell rendelnünk. Tehát ha egy menüre rákattintunk az triggerelni fogja az akciónkat, amely ezáltal a emittálja a triggered() szignálját, amely meghívja a hozzákötött szlotokat. | |||
<br />h3. További olvasnivalók:<br />|''. Miről |''. Hol |<br />| Főablak és egyéb ablakok | "Application Main Window&quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples&quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html |<br />| MDI alkalmazások | "QMdiArea&quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example&quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html | | |||
<br />A következő kódrészletben implementálni fogjuk a mentés és megnyitás kezelésére szolgáló szlotokat. | |||
<br />Kezdjük az open() szlottal: | |||
<br /><code><br /> QString fileName = QFileDialog::getOpenFileName(this, tr("Open File&quot;), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)")); | |||
if (fileName != "") {<br /> QFile file&amp;#40;fileName&amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr("Error&quot;),<br /> tr("Could not open file&quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit->setPlainText(contents);<br /> file.close();<br /> }<br /></code> | |||
Első lépésként bekérjük a felhasználótól a fájl nevét. A Qt-ban direkt erre a feladatra van egy osztály a "QFileDialog&quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html , amely egy dialógus megjelenítésére szolgál, amelyből a felhasználó kitallózhatja a kívánt fájlt. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|A képen ezt a dialógust láthatjuk, ahogyan az KUbuntun megjelenik.]] | |||
A "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName) statikus metódus egy dialógust jelenít meg (az alkalmazás többi ablaka nem használható ameddig jelen van), és addig nem tér vissza amíg a felhasználó ki nem választott egy fájlt. A visszatérési értékben megkapjuk a fájl elérési útját, vagy egy üres sztringet, ha a felhasználó a mégsem gombra kattintott. | |||
Ha megvan az érvényes fájlnév, akkor megnyitjuk a fájlt a QFile "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open metódusával, amely igazzal tér vissza, ha a megnyitás sikerült. Most nem megyünk bele a hibakezelésbe, de ha érdekel, utána nézhetsz ezeknek a További információ szekcióban. Ha a fájl nem nyitható meg, akkor egy "QMessageBox&quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html-ban jelenítjük meg a hibaüzenetet. A részletekért lásd a "QMessageBox&quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html osztály súgóját. | |||
Az adatok beolvasása triviális a "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll metódusának köszönhetően. Ez a függvény egy a fájlban lévő adatokat tartlmazó "QByteArray&quot;:http://doc.qt.nokia.com/4.7/qbytearray.htm <s>jel tér vissza. A QByteArray "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData metódusa segítségével az adatokat const char* formában is elérhetjük, amit már át tudunk adni a "QString&quot;:http://doc.qt.nokia.com/4.7/qstring.html konstruktorának. Így a fájl tartalma megjeleníthető a szövegdobozban. Végül a "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close metódussal bezárjuk a fájlt, így adva vissza a fájlleírót az operációs rendszernek. | |||
<br />Most, hogy letudtuk a megnyitás szlotot lássuk a mentést: | |||
<br /><code><br /> QString fileName = QFileDialog::getSaveFileName(this, tr("Save File&quot;), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)")); | |||
<br /> if (fileName != "") {<br /> QFile file&amp;#40;fileName&amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&file);<br /> stream << textEdit</s>>toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br /></code> | |||
Miután megszerkesztettük a szövegdobozunk tartalmát, azt a "QTextStream&quot;:http://doc.qt.nokia.com/4.7/qtextstream.html objektumon keresztül írjuk vissza a fájlunkba. Ez az osztály mintegy ráépül a "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html objektumunkra, lehetővé téve, hogy a neki küldött szövegeket direktben kiírassuk a fájlunkba. | |||
=== További olvasnivalók:<br />|''. Miről |''. Hol | === | |||
Revision as of 09:39, 24 February 2015
Magyar
Bevezetés a Qt programozás alapjaiba
Üdvözöllek a Qt keresztplatformos fejlesztői rendszer világában. Ebben a leírásban egy egyszerű jegyzettömb alkalmazás elkészítése során bemutatjuk a Qt programozás alapfogásait. Az útmutató tanulmányozása során nyugodtan nézz bele az API dokumentációba, amennyiben valamivel kapcsolatban több információra van szükséged.
Az útmutató angol nyelvű változata elérhető az "http://doc.qt.nokia.com/gettingstartedqt.html":http://doc.qt.nokia.com/gettingstartedqt.html oldalon.
Hello Jegyzettömb
Példánkban egy egyszerű szövegdobozt hozunk létre egy ablakkeretben. Ez lesz a legegyszerűbb felhasználói felülettel rendelkező Qt segítségével írt program.
p=. Notepad
Íme a kód:
#include <QApplication&gt;<br />#include <QTextEdit&gt;
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
QTextEdit textEdit;<br /> textEdit.show();
return app.exec&amp;#40;&#41;;<br />}
Vizsgáljuk meg a kódot sorról sorra. Az első két sorban a "QApplication":http://doc.qt.nokia.com/qapplication.html és a "QTextEdit":http://doc.qt.nokia.com/qtextedit.html osztály használatához szükséges headerfájlokat includoljuk be a programunkba. A Qt összes osztályának megvan a nevével megegyező headerje.
A 6. sorban létrehozunk egy "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html objektumot. Ez az objektum kezeli az alkalmazás összes erőforrását. Egy ilyen objektum létrehozása szükséges minden grafikus Qt alkalmazáshoz. Argumentumként át kell adni az argv és args paramétereket, mivel a Qt-ban írt alkalmazásoknak "van néhány beépített parancssori argumentuma":http://doc.trolltech.com/4.7/qapplication.html#QApplication.
A 8. sorban létrehozunk egy "QTextEdit":http://doc.qt.nokia.com/qtextedit.html objektumot. Ez a szövegdoboz egy megjeleníthető grafikus elem. A Qt-ban az ilyeneket widgeteknek hívjuk. További widgetek például: gördítősávok, címkék, rádiógombok. Minden widget lehet egyfajta konténer további widgetek számára, mint például egy ablak, vagy egy dialógus.
A 9. sorban megjelenítjük a szövegdobozt a saját ablakkeretében. Mint már említettem, a widgetek konténerként is funkcionálnak mint például a "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, amelynek van menüsora, státuszsora, és még néhány egyéb beépített widgete. Továbbá lehetőség van egyetlen widget megjelenítésére is főablakba helyezés nélkül, ez esetben maga a widget kap egy ablakkeretet. A widgetek alapból nem láthatóak, a show() metódus meghívása teszi őket azzá.
A 11. sorban meghívjuk a "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html eseménykezelő rutinját. Ha egy Qt alkalmazás futása közben esemény történik, akkor az kiküldődik a megfelelő widgethez. Például az egérkattintás és a billentyűleütések esetében a szövegdobozunk fogja megkapni ezeket az eseményeket. Az ilyen és ehhez hasonló feladatokat intézi ez a metódus.
Az alakalmazás fordításához és futtatásához nyiss meg egy parancssort, lépj be abba a mappában, ahol a .cpp fájlod található, és futtasd le a következő parancsokat:
<br /> qmake -project<br /> qmake<br /> make<br />
Ezen műveletek után egy futtatható binárisnak kell megjelennie a part1 mappában. (Megjegyzés a Windowst és VisualStudiot használóknak: a make nmaket kell futtatniuk, továbbá a bináris a part1/debug vagy part1/release mappában fog létrejönni.)
A qmake a Qt build eszköze ami argumentum nélkül egy projekt fájlt keres, amit fel tud dolgozni. A project argumentummal létrehoz automatikusan egy .pro fájlt a mappában található fájlokat hozzáadva. A qmaket futtatva létrejön a Makefile, amit a make programod fog feldolgozni. A .pro fájlok írásáról később még lesz szó. Amennyiben Windows alatt valamit hiányolna a fordítás során, akkor keresd ki a start menüből a Qt Command prompt-ot, és abból futtasd a parancsokat.
h3. További olvasnivalók:
|. Miről |. Hol |
| Widgetek és ablakok geometriája | "Window and Dialog Widgets":http://doc.qt.nokia.com/4.7/application-windows.html |
| Események és a Qt eseménykezelője | "The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html |
h2. Kilépés gomb hozzáadása
Egy igazi alkalmazásban általában egynél több widgetre van szükséged. Helyezzünk egy "QPushButtont":http://doc.qt.nokia.com/4.7/qpushbutton.html a szövegdoboz alá. Ez arra fog szolgálni, hogy ha a felhasználó rákattint, a program lépjen ki.
p=. Eingabefeld mit Beenden Knopf
Nézzük a kódot:
<br />#include <QtGui&gt;
<br />int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> QPushButton quitButton("Quit&quot;);
<br /> QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br /> QVBoxLayout layout;<br /> layout.addWidget(&textEdit);<br /> layout.addWidget(&quitButton);
<br /> QWidget window;<br /> window.setLayout(&layout);
<br /> window.show();
<br /> return app.exec&amp;#40;&#41;;<br />}<br />
Az első sorban beincludoljuk a "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html headert, ami magában foglalja a Qt összes grafikus osztályát.
A tizedik sorban a Qt szignál slot mechanizmusa segítségével lekezeljük a Kilépés gomb megnyomását.
A szlot függvény a futás során hívódik meg a neve segítségével. A szignálok olyan függvények, amelyek a megfelelő esemény bekövetkezésekor automatikusan meghívják a hozzájuk csatlakoztatott slotokat. Esetünkben a "quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit a widgetünk egy beépített slotja, amelyet meghívva az alkalmazás kilép. A gombunk "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked szignálja pedig a gomb megnyomásakor emittálódik. A szignál-slot hozzárendelést a statikus "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html# függvénnyel hozhatjuk létre. Az argumentumként használt SIGNAL () és SLOT() makrókban kell megadnunk a megfelelő függvényneveket, azok argumentumainak típusával egyetemben. A connect() függvénynek át kell adni a küldő és fogadó objektumokra mutató mutatókat is.
A 12. sorban egy "QVBoxLayout-ot":http://doc.qt.nokia.com/4.7/qvboxlayout.html hozunk létre. Ahogy már említettük a widgetek (szülő widget) tartalmazhatnak további widgeteket (gyermek widgetek). Lehetőségünk van a gyermek widgeteknek pontos méretet, pozíciót megadni, de egyszerűbb, ha ehelyett layoutokat használunk, így a azok fogják kezelni a gyermekwidgetek elrendezését. A "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html például a gyermekeket egy függőleges oszlopba rendezi.
A 13. és 14. sorban hozzáadjuk a szövegdobozunkat és a nyomógombunkat a layouthoz, majd a 17. sorban érvénybe léptetjük az elrendezést.
h3. További olvasnivalók:
|. Miről |. Hol |
| Szignálok és Szlotok | "Signals & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html |
| Layoutok | "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 |
| A QT beépített widgetkészlete | "Qt Widget Gallery":http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples":http://doc.qt.nokia.com/4.7/examples-widgets.html |
h2. Származtatás a QWidget osztályból
Miután a felhasználó a kilépés gombra kattint, sok esetben érdemes egy megerősítést kérő ablakot megjeleníteni, hogy valóban ki akar-e lépni. Példánkban a "QWidget":http://doc.qt.nokia.com/4.7/qwidget.html osztályból származtatjuk a programfelület legfelsőbbb osztályát, és létrehozunk egy slotot, amihez hozzákötjük a Kilépés gomb kattintás szignálját.
Íme a kód:
<br /> class Notepad : public QWidget<br /> {<br /> Q_OBJECT
<br /> public:<br /> Notepad();
<br /> private slots:<br /> void quit();
<br /> private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br /> };<br />
A Q_OBJECT makrónak kell az osztálydeklaráció elején lennie. Ez a makró az osztályunkat "QObjectként":http://doc.qt.nokia.com/4.7/qobject.html deklarálja (természetesen a használatához a "QObjecttől":http://doc.qt.nokia.com/4.7/qobject.html kell származtatnunk). Ez a példánkban is így van, hiszen a QWidget osztály a QObjectből van származtatva. A "QObject":http://doc.qt.nokia.com/4.7/qobject.html különféle funkciókkal bővíti ki a C++ osztályok tulajdonságait. Például az osztály és szlotok neve lekérdezhetővé válik futásidőben. Továbbá lehetőség van a szlotok argumentumainak típusát lekérdezni, illetve név alapján meghívni azokat.
A 9. sorban deklaráljuk a quit() szlotot a slots makró segítségével. A slotunkat ezután hozzáköthetjük bármilyen szignálhoz, amelynek nincs argumentuma.
A következőekben létrehozunk egy Notepad osztályt, amelynek a konstruktorában hozzuk létre a felületet, és kötjük össze a slotokat a szignálokkal. Ez megoldás elegánsabb, mint ha ezt a main() függvényben tennénk meg.
<br /> Notepad::Notepad()<br /> {<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr("Quit&quot;));
<br /> connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
<br /> QVBoxLayout *layout = new QVBoxLayout;<br /> layout</s>>addWidget(textEdit);<br /> layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Notepad&quot;));<br /> }<br />
Amint láthatod mutatókat használunka textEdit és a quitButton elérésére. Az ilyen grafikus elemeket mindig a heapen példányosítjuk, és sohasem másoljuk őket.
Az ablak címét a setWindowTitle metódus segítségével állítjuk be. Amint láthatod a felhasználó számára látható szöveget a "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr függvényen keresztül adjuk át a függvénynek. Ez a függvény a többnyelvű alkalmazások írásánál nyújt segítséget. Most nem megyünk bele a részletekbe, további információt a "Qt Linguist":http://doc.qt.nokia.com/4.7/linguist-manual.html dokumentációjánál találsz.
További olvasnivalók:
|. Miről |. Hol |
| tr() és a többnyelvűsítés | "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 |
| "QObject":http://doc.qt.nokia.com/4.7/qobject.html és a Qt objektummodell-rendszere | "Object Model":http://doc.qt.nokia.com/4.7/object.html |
| qmake a Qt build rendszere | "qmake Manual":http://doc.qt.nokia.com/4.7/qmake-manual.html |
Az elkövetkezőkben írunk egy saját .pro fájlt, ahelyett, hogy a qmake-el generáltatnánk le.
HEADERS = notepad.h<br /> SOURCES = notepad.cpp main.cpp
A következő parancsokkal tudod lefordítani a példát:
qmake<br /> make
A QMainWindow használata
Sok alkalmazás írásakor kézenfekvő lehet a használata, ugyanis ez az osztály egy előre megadott layout-ot tartalmaz, amelyre elhelyezhetjük saját menü sorunkat, eszköztárainkat, a dokkolható widgetek számára rögzítési területet, illetve az állapotsort is.
A "QMainWindownak":http://doc.qt.nokia.com/4.7/qmainwindow.html van egy középső területe, ahol elhelyezhetünk bármilyen widgetet. Esetünkben is ide fog kerülni a szövegdobozunk.
p=. QMainWindow
Tekintsük át a Notepad osztály definícióját!
<br /> #include <QtGui&gt;
class Notepad : public QMainWindow<br /> {<br /> Q_OBJECT
public:<br /> Notepad();
private slots:<br /> void open();<br /> void save();<br /> void quit();
private:<br /> QTextEdit *textEdit;
QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
QMenu '''fileMenu;<br /> };<br />
Az elkövetkezendőkben implementálni fogunk két slotot, mely a dokumentum megnyitására és mentésére fog szolgálni.
A fő ablakokban gyakran megesik az, hogy egy szlotot több widget is meghív. Esetünkben a menü egyes elemei és az eszköztár gombjai is ezt teszik. Az ilyen esetek leegyszerűsítésére hozták létre a "QAction":http://doc.qt.nokia.com/4.7/qaction.html osztályt, amelyet átadhatunk több widgetnek is, majd hozzákötjük a megfelelő szlothoz a szignálját. Például a "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html és a "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html is létrehozhat menüket, eszköztárelemeket ugyanannak a "QAction":http://doc.qt.nokia.com/4.7/qaction.html nek a hatására.
Ahogyan már említettük a grafikus elemeket a Notepad osztály konstruktorában inicializáljuk.
<br /> Notepad::Notepad()<br /> {<br /> saveAction = new QAction(tr("&Open&quot;), this);<br /> saveAction = new QAction(tr("&Save&quot;), this);<br /> exitAction = new QAction(tr("E&amp;xit&quot;), 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()</s>>addMenu(tr("&File&quot;));<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&quot;));<br /> }<br />
A "QAction-ök":http://doc.qt.nokia.com/4.7/qaction.html konstruktorának egy szöveget adunk meg argumentumként. Ez a szöveg fog megjelenni azokon a widgeteken, amelyekhez hozzárendeljük őket (esetünkben a menüelemeken). Ha ugyanazt a funkciót el szeretnénk érni az eszköztárunkról is, akkor az akcióhoz ikont is kell rendelnünk. Tehát ha egy menüre rákattintunk az triggerelni fogja az akciónkat, amely ezáltal a emittálja a triggered() szignálját, amely meghívja a hozzákötött szlotokat.
h3. További olvasnivalók:
|. Miről |. Hol |
| Főablak és egyéb ablakok | "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 |
| MDI alkalmazások | "QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html |
A következő kódrészletben implementálni fogjuk a mentés és megnyitás kezelésére szolgáló szlotokat.
Kezdjük az open() szlottal:
<br /> QString fileName = QFileDialog::getOpenFileName(this, tr("Open File&quot;), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)"));
if (fileName != "") {<br /> QFile file&amp;#40;fileName&amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr("Error&quot;),<br /> tr("Could not open file&quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit->setPlainText(contents);<br /> file.close();<br /> }<br />
Első lépésként bekérjük a felhasználótól a fájl nevét. A Qt-ban direkt erre a feladatra van egy osztály a "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html , amely egy dialógus megjelenítésére szolgál, amelyből a felhasználó kitallózhatja a kívánt fájlt.
p=. A képen ezt a dialógust láthatjuk, ahogyan az KUbuntun megjelenik.
A "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName) statikus metódus egy dialógust jelenít meg (az alkalmazás többi ablaka nem használható ameddig jelen van), és addig nem tér vissza amíg a felhasználó ki nem választott egy fájlt. A visszatérési értékben megkapjuk a fájl elérési útját, vagy egy üres sztringet, ha a felhasználó a mégsem gombra kattintott.
Ha megvan az érvényes fájlnév, akkor megnyitjuk a fájlt a QFile "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open metódusával, amely igazzal tér vissza, ha a megnyitás sikerült. Most nem megyünk bele a hibakezelésbe, de ha érdekel, utána nézhetsz ezeknek a További információ szekcióban. Ha a fájl nem nyitható meg, akkor egy "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html-ban jelenítjük meg a hibaüzenetet. A részletekért lásd a "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html osztály súgóját.
Az adatok beolvasása triviális a "QFile":http://doc.qt.nokia.com/4.7/qfile.html "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll metódusának köszönhetően. Ez a függvény egy a fájlban lévő adatokat tartlmazó "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.htm jel tér vissza. A QByteArray "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData metódusa segítségével az adatokat const char* formában is elérhetjük, amit már át tudunk adni a "QString":http://doc.qt.nokia.com/4.7/qstring.html konstruktorának. Így a fájl tartalma megjeleníthető a szövegdobozban. Végül a "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close metódussal bezárjuk a fájlt, így adva vissza a fájlleírót az operációs rendszernek.
Most, hogy letudtuk a megnyitás szlotot lássuk a mentést:
<br /> QString fileName = QFileDialog::getSaveFileName(this, tr("Save File&quot;), "",<br /> tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)"));
<br /> if (fileName != "") {<br /> QFile file&amp;#40;fileName&amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&file);<br /> stream << textEdit</s>>toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br /> }<br />
Miután megszerkesztettük a szövegdobozunk tartalmát, azt a "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html objektumon keresztül írjuk vissza a fájlunkba. Ez az osztály mintegy ráépül a "QFile":http://doc.qt.nokia.com/4.7/qfile.html objektumunkra, lehetővé téve, hogy a neki küldött szövegeket direktben kiírassuk a fájlunkba.