Basic Programming/hu: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Category:Learning]][[Category:Hungarian]] | [[Category:Learning]][[Category:Hungarian]] | ||
'''Magyar''' | |||
= Bevezetés a Qt programozás alapjaiba = | = Bevezetés a Qt programozás alapjaiba = | ||
Line 5: | Line 6: | ||
Ü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. | Ü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 | 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 == | == Hello Jegyzettömb == | ||
Line 13: | Line 14: | ||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Notepad]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Notepad]] | ||
Íme a kód: | Íme a kód: | ||
<code>#include <QApplication> | |||
#include <QTextEdit> | |||
int main(int argv, char **args) | int main(int argv, char **args) | ||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | QTextEdit textEdit; | ||
textEdit.show(); | |||
return app.exec | return app.exec(); | ||
}</code> | |||
Vizsgáljuk meg a kódot sorról sorra. Az első két sorban a | 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 | 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 | 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 | 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 | 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: | 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> | <code> | ||
qmake -project | |||
qmake | |||
make | |||
</code> | |||
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.) | 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=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Eingabefeld mit Beenden Knopf]] | |||
Nézzük a kódot: | |||
<code> | |||
#include <QtGui> | |||
int main(int argv, char **args) | |||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | |||
QPushButton quitButton("Quit"); | |||
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | |||
QVBoxLayout layout; | |||
layout.addWidget(&textEdit); | |||
layout.addWidget(&quitButton); | |||
QWidget window; | |||
window.setLayout(&layout); | |||
window.show(); | |||
return app.exec(); | |||
} | |||
</code> | |||
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: | |||
<code> | |||
class Notepad : public QWidget | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QPushButton *quitButton; | |||
}; | |||
</code> | |||
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. | |||
<code> | |||
Notepad::Notepad() | |||
{ | |||
textEdit = new QTextEdit; | |||
quitButton = new QPushButton(tr("Quit")); | |||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | |||
QVBoxLayout *layout = new QVBoxLayout; | |||
layout->addWidget(textEdit); | |||
layout->addWidget(quitButton); | |||
setLayout(layout); | setLayout(layout); | ||
setWindowTitle(tr( | setWindowTitle(tr("Notepad")); | ||
} | |||
</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":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: | ||
|''. 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. | Az elkövetkezőkben írunk egy saját .pro fájlt, ahelyett, hogy a qmake-el generáltatnánk le. | ||
<code> HEADERS = notepad.h | <code> HEADERS = notepad.h | ||
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: | ||
<code> qmake | <code> qmake | ||
make</code> | |||
= A QMainWindow használata = | = 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. | 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=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|QMainWindow]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|QMainWindow]] | ||
Line 95: | Line 179: | ||
Tekintsük át a Notepad osztály definícióját! | Tekintsük át a Notepad osztály definícióját! | ||
<code>< | <code> | ||
#include <QtGui> | |||
class Notepad : public QMainWindow | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void open(); | |||
void save(); | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QAction *openAction; | |||
QAction *saveAction; | |||
QAction *exitAction; | |||
QMenu '''fileMenu; | |||
}; | |||
</code> | |||
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. | |||
<code> | |||
Notepad::Notepad() | |||
{ | |||
saveAction = new QAction(tr("&Open"), this); | |||
saveAction = new QAction(tr("&Save"), this); | |||
exitAction = new QAction(tr("E&amp;xit"), this); | |||
connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | |||
connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | |||
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | |||
fileMenu = menuBar()->addMenu(tr("&File")); | |||
fileMenu->addAction(openAction); | |||
fileMenu->addAction(saveAction); | |||
fileMenu->addSeparator(); | |||
fileMenu->addAction(exitAction); | |||
textEdit = new QTextEdit; | |||
setCentralWidget(textEdit); | |||
setWindowTitle(tr("Notepad")); | |||
} | |||
</code> | |||
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: | |||
<code> | |||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | |||
tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)")); | |||
if (fileName != | if (fileName != "") { | ||
QFile file(fileName); | |||
if (!file.open(QIODevice::ReadOnly)) { | |||
QMessageBox::critical(this, tr("Error"), | |||
tr("Could not open file")); | |||
return; | |||
} | |||
QString contents = file.readAll().constData(); | |||
textEdit->setPlainText(contents); | |||
file.close(); | |||
} | |||
</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 | 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=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|A képen ezt a dialógust láthatjuk, ahogyan az KUbuntun megjelenik.]] | 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 | 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: | |||
<code> | |||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", | |||
tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::WriteOnly)) { | |||
// error message | |||
} else { | |||
QTextStream stream(&file); | |||
stream << textEdit->toPlainText(); | |||
stream.flush(); | |||
file.close(); | |||
} | |||
} | |||
</code> | |||
Miután megszerkesztettük a szövegdobozunk tartalmát, azt a | 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. | ||
=== További olvasnivalók: | === További olvasnivalók: | ||
|''. Miről |''. Hol | === |
Revision as of 10:00, 25 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>
#include <QTextEdit>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
textEdit.show();
return app.exec();
}
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:
qmake -project
qmake
make
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:
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
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:
class Notepad : public QWidget
{
Q_OBJECT
public:
Notepad();
private slots:
void quit();
private:
QTextEdit *textEdit;
QPushButton *quitButton;
};
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.
Notepad::Notepad()
{
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Quit"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Notepad"));
}
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
SOURCES = notepad.cpp main.cpp
A következő parancsokkal tudod lefordítani a példát:
qmake
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!
#include <QtGui>
class Notepad : public QMainWindow
{
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu '''fileMenu;
};
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.
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&amp;xit"), this);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
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:
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
return;
}
QString contents = file.readAll().constData();
textEdit->setPlainText(contents);
file.close();
}
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:
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// error message
} else {
QTextStream stream(&file);
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
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.
=== További olvasnivalók: |. Miről |. Hol | ===