Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Basic Programming/hu: Difference between revisions
No edit summary |
m (Apró javtás.) |
||
(9 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Learning]][[Category:Hungarian]] | {{Cleanup | reason=Auto-imported from ExpressionEngine.}} | ||
[[Category:Learning]][[Category:Hungarian]] | |||
'''Magyar''' | |||
= Bevezetés a Qt programozás alapjaiba = | = Bevezetés a Qt programozás alapjaiba = | ||
Line 5: | Line 8: | ||
Ü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 16: | ||
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 [http://doc.qt.nokia.com/qapplication.html QApplication] és a [http://doc.qt.nokia.com/qtextedit.html QTextEdit] osztály használatához szükséges headerfájlokat csatoljuk be 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 [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] 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 [http://doc.trolltech.com/4.7/qapplication.html#QApplication van néhány beépített parancssori argumentuma]. | ||
A 8. sorban létrehozunk egy | A 8. sorban létrehozunk egy [http://doc.qt.nokia.com/qtextedit.html QTextEdit] objektumot. Ez a szövegdoboz egy megjeleníthető grafikus elem. A Qt-ban az ilyeneket widgeteknek ( kütyüknek, szerkezeteknek, szerkentyűknek ) hívjuk. További szerkentyűk például: gördítősávok, címkék, rádiógombok. Minden szerkentyű lehet egyfajta tárolója további szerkentyűk 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 | A 9. sorban megjelenítjük a szövegdobozt a saját ablakkeretében. Mint már említettem, a szerkentyűk tárolóként is szerepelnek, mint például a [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow], amelynek van menüsora, állapotsora, és még néhány egyéb beépített szerkentyűje. Továbbá lehetőség van egyetlen szerkentyű megjelenítésére is főablakba helyezés nélkül, ez esetben maga a szerkentyű kap egy ablakkeretet. A szerkentyűk 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 [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] eseménykezelő alprogramját. Ha egy Qt alkalmazás futása közben esemény történik, akkor annak híre eljut a megfelelő szerkentyűhöz. Például az egérkattintás és a billentyűleütések esetében a szövegdobozunk fogja megkapni a híreket ezekről az eseményekről. 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.) | |||
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. | |||
=== További olvasnivalók: === | |||
|''. Miről |''. Hol | | |||
| Widgetek és ablakok geometriája | [http://doc.qt.nokia.com/4.7/application-windows.html Window and Dialog Widgets] | | |||
| Események és a Qt eseménykezelője | [http://doc.qt.nokia.com/4.7/eventsandfilters.html The Event System] | | |||
== Kilépés gomb hozzáadása == | |||
Egy igazi alkalmazásban általában egynél több szerkentyűre van szükséged. Helyezzünk egy [http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButtont] a szövegdoboz alá. Ez arra szolgál majd, hogy ha a felhasználó rákattint, a program kilépjen. | |||
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 becsatoljuk a [http://doc.qt.nokia.com/4.7/qtgui.html QtGui] headert, ami magában foglalja a Qt összes grafikus osztályát. | |||
A tizedik sorban a Qt ( signál slot ) jel rés mechanizmusa segítségével lekezeljük a Kilépés gomb megnyomását. | |||
A rés függvény a futás során hívódik meg a neve segítségével. A jelek olyan függvények, amelyek a megfelelő esemény bekövetkezésekor automatikusan meghívják a hozzájuk csatlakoztatott réseket. Esetünkben a [http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit quit()] a szerkentyűnk egy beépített rése, amelyet meghívva az alkalmazás kilép. A gombunk [http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked clicked()] jele pedig a gomb megnyomásakor lesz kibocsátva. A jel-rés hozzárendelést a statikus [http://doc.qt.nokia.com/4.7/qobject.html# QObject::connect()] 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 [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout-ot] hozunk létre. Ahogy már említettük a szerkentyűk (szülő szerkentyűk) tartalmazhatnak további szerkentyűket (gyermek szerkentyűket). Megadhatjuk a gyermek szerkentyűk pontos méretet és helyzetét, de egyszerűbb, ha ehelyett (layoutokat) elrendezéseket használunk, így ezek kezelik majd a gyermekszerkentyűk elrendezését. A [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] például a gyermek szerkentyűket egy függőleges oszlopba rendezi. | |||
A 13. és 14. sorban hozzáadjuk a szövegdobozunkat és a nyomógombunkat az elrendezéshez, majd a 17. sorban érvénybe léptetjük az elrendezést. | |||
=== További olvasnivalók: === | |||
|''. Miről |''. Hol | | |||
| Szignálok és Szlotok | [http://doc.qt.nokia.com/4.7/signalsandslots.html Signals & Slots] | | |||
| Layoutok | [http://doc.qt.nokia.com/4.7/layout.html Layout Management], [http://doc.qt.nokia.com/4.7/widgets-and-layouts.html Widgets and Layouts], [http://doc.qt.nokia.com/4.7/examples-layouts.html Layout Examples] | | |||
| A QT beépített widgetkészlete | [http://doc.qt.nokia.com/4.7/gallery.html Qt Widget Gallery], [http://doc.qt.nokia.com/4.7/examples-widgets.html Widget Examples] | | |||
== 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 [http://doc.qt.nokia.com/4.7/qwidget.html QWidget] osztályból származtatjuk a programfelület legfelsőbb osztályát, és létrehozunk egy rést, amihez hozzákötjük a Kilépés gomb kattintás jelé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ály kihírdetésének elején lennie. Ez a makró az osztályunkat [http://doc.qt.nokia.com/4.7/qobject.html QObjectként] deklarálja (természetesen a használatához a [http://doc.qt.nokia.com/4.7/qobject.html QObjecttől] kell származtatnunk). Ez a példánkban is így van, hiszen a QWidget osztály a QObjectből van származtatva. A [http://doc.qt.nokia.com/4.7/qobject.html QObject] különféle funkciókkal bővíti ki a C++ osztályok tulajdonságait. Például az osztály és rések neve lekérdezhetővé válik futásidőben. Továbbá lehetőség van a rések argumentumainak típusát lekérdezni, illetve név alapján meghívni azokat. | |||
A 9. sorban meghírdetjük a quit() rést a '''slots''' makró segítségével. A résünket ezután hozzáköthetjük bármilyen jelhez, amelynek nincs argumentuma. | |||
A következőkben létrehozunk egy Notepad osztályt, amelynek a elem-felépítőjében ( constructor ) hozzuk létre a felületet, és kötjük össze a réseket a jelekkel. Ez a 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 | Amint láthatod, mutatókat használunk a textEdit és a quitButton elérésére. Az ilyen grafikus elemeket mindig a ( heap -en ) halmon 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 [http://doc.qt.nokia.com/4.7/qobject.html#tr 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 részletezzük, további információt a [http://doc.qt.nokia.com/4.7/linguist-manual.html Qt Linguist] 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 | [http://doc.qt.nokia.com/4.7/linguist-manual.html Qt Linguist Manual], [http://doc.qt.nokia.com/4.7/i18n-source-translation.html Writing Source Code for Translation], [http://doc.qt.nokia.com/4.7/linguist-hellotr.html Hello tr()] Example, [http://doc.qt.nokia.com/4.7/internationalization.html Internationalization with Qt] | | |||
| [http://doc.qt.nokia.com/4.7/qobject.html QObject] és a Qt objektummodell-rendszere | [http://doc.qt.nokia.com/4.7/object.html Object Model] | | |||
| qmake a Qt build rendszere | [http://doc.qt.nokia.com/4.7/qmake-manual.html qmake Manual] | === | |||
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 | Sok alkalmazás írásakor kézenfekvő lehet a használata, ugyanis ez az osztály egy előre megadott elrendezést ( layout ) tartalmaz, amelyre elhelyezhetjük saját menü sorunkat, eszköztárainkat, a kiköthető szerkentyűk számára rögzítési területet, illetve az állapotsort is. | ||
A [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindownak] van egy középső területe, ahol elhelyezhetünk bármilyen szerkentyűt. 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 majd megvalósítunk két rést, mely a dokumentum megnyitására és mentésére fog szolgálni. | |||
A fő ablakokban gyakran megesik az, hogy egy rést több szerkentyű 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 [http://doc.qt.nokia.com/4.7/qaction.html QAction] osztályt, amelyet átadhatunk több szerkentyűnek is, majd a jelét a megfelelő résekhez köthetjük. Például a [http://doc.qt.nokia.com/4.7/qmenu.html QMenu] és a [http://doc.qt.nokia.com/4.7/qtoolbar.html QToolBar] is létrehozhat menüket, eszköztárelemeket ugyanannak a [http://doc.qt.nokia.com/4.7/qaction.html QAction] -nek a hatására. | |||
Ahogyan már említettük, a grafikus elemeknek a Notepad osztály elem-felépítőjében adunk kezdőértéket. | |||
<code> | |||
Notepad::Notepad() | |||
{ | |||
saveAction = new QAction(tr("&Open"), this); | |||
saveAction = new QAction(tr("&Save"), this); | |||
exitAction = new QAction(tr("E&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 [http://doc.qt.nokia.com/4.7/qaction.html QAction-ök] elem-felépítőjében egy szöveget adunk meg argumentumként. Ez a szöveg fog megjelenni azokon a szerkentyűkön, amelyekhez rendeljük őket (esetünkben a menüelemeken). Ha ugyanazt a funkciót el szeretnénk érni az eszköztárunkról is, akkor a művelethez ( action ) jelképet ( icon ) is kell rendelnünk. Tehát, ha egy menüre rákattintunk, az majd bekapcsolja a műveletünket, amely ezáltal elküldi a triggered() jelét, amely meghívja a hozzákötött réseket. | |||
=== További olvasnivalók: === | |||
|''. Miről |''. Hol | | |||
| Főablak és egyéb ablakok | [http://doc.qt.nokia.com/4.7/mainwindow.html Application Main Window], [http://doc.qt.nokia.com/4.7/examples-mainwindow.html Main Window Examples] | | |||
| MDI alkalmazások | [http://doc.qt.nokia.com/4.7/qmdiarea.html QMdiArea], [http://doc.qt.nokia.com/4.7/mainwindows-mdi.html MDI Example] | | |||
A következő kódrészletben majd megvalósítjuk a mentés és megnyitás kezelésére szolgáló réseket. | |||
Kezdjük az open() réssel: | |||
<code> | |||
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(); | |||
} | |||
</code> | |||
Első lépésként bekérjük a felhasználótól a fájl nevét. A Qt-ban pont e feladatra van egy osztály a [http://doc.qt.nokia.com/4.7/qfiledialog.html QFileDialog] , amely egy párbeszédablak 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 párbeszédablakot láthatjuk, ahogyan az KUbuntun megjelenik.]] | |||
A [http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName getOpenFileName()]) statikus metódus egy párbeszédablakot jelenít meg (az alkalmazás többi ablaka nem használható addig, 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 betűjelsort, ha a felhasználó a mégsem gombra kattintott. | |||
Ha megvan az érvényes fájlnév, akkor megnyitjuk a fájlt a QFile [http://doc.qt.nokia.com/4.7/qiodevice.html#open open()] metódusával, amely igazzal tér vissza, ha a megnyitás sikerült. Most nem részletezzük a hibakezelés, de ha érdekel, utánanézhetsz ezeknek a További információ részben. Ha a fájl nem nyitható meg, akkor egy [http://doc.qt.nokia.com/4.7/qmessagebox.html-ban QMessageBox] jelenítjük meg a hibaüzenetet. A részletekért lásd a [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] osztály súgóját. | |||
Az adatok beolvasása egyértelmű a [http://doc.qt.nokia.com/4.7/qfile.html QFile] [http://doc.qt.nokia.com/4.7/qiodevice.html#readAll readAll()] metódusának köszönhetően. Ez a függvény, egy a fájlban lévő adatokat tartalmazó [http://doc.qt.nokia.com/4.7/qbytearray.htm QByteArray] -jel tér vissza. A QByteArray [http://doc.qt.nokia.com/4.7/qbytearray.html#constData constData()] metódusa segítségével az adatokat const char* formában is elérhetjük, amit már átadhatunk a [http://doc.qt.nokia.com/4.7/qstring.html QString] elem-felépítőnek. Így a fájl tartalma megjeleníthető a szövegdobozban. Végül a [http://doc.qt.nokia.com/4.7/qiodevice.html#close close()] metódussal bezárjuk a fájlt, így adva vissza a fájl-leírót az operációs rendszernek. | |||
Most, hogy megvagyunka megnyitás réssel, 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 [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] objektumon keresztül írjuk vissza a fájlunkba. Ez az osztály mintegy ráépül a [http://doc.qt.nokia.com/4.7/qfile.html QFile] objektumunkra, lehetővé téve, hogy a neki küldött szövegeket közvetlenül a fájlunkba írhassuk. | ||
=== További olvasnivalók: | === További olvasnivalók: | ||
|''. Miről |''. Hol | === |
Latest revision as of 14:53, 4 February 2017
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine. Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean. |
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 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 és a QTextEdit osztály használatához szükséges headerfájlokat csatoljuk be programunkba. A Qt összes osztályának megvan a nevével megegyező headerje.
A 6. sorban létrehozunk egy QApplication 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.
A 8. sorban létrehozunk egy QTextEdit objektumot. Ez a szövegdoboz egy megjeleníthető grafikus elem. A Qt-ban az ilyeneket widgeteknek ( kütyüknek, szerkezeteknek, szerkentyűknek ) hívjuk. További szerkentyűk például: gördítősávok, címkék, rádiógombok. Minden szerkentyű lehet egyfajta tárolója további szerkentyűk 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 szerkentyűk tárolóként is szerepelnek, mint például a QMainWindow, amelynek van menüsora, állapotsora, és még néhány egyéb beépített szerkentyűje. Továbbá lehetőség van egyetlen szerkentyű megjelenítésére is főablakba helyezés nélkül, ez esetben maga a szerkentyű kap egy ablakkeretet. A szerkentyűk alapból nem láthatóak, a show() metódus meghívása teszi őket azzá.
A 11. sorban meghívjuk a QApplication eseménykezelő alprogramját. Ha egy Qt alkalmazás futása közben esemény történik, akkor annak híre eljut a megfelelő szerkentyűhöz. Például az egérkattintás és a billentyűleütések esetében a szövegdobozunk fogja megkapni a híreket ezekről az eseményekről. 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.
További olvasnivalók:
|. Miről |. Hol | | Widgetek és ablakok geometriája | Window and Dialog Widgets | | Események és a Qt eseménykezelője | The Event System |
Kilépés gomb hozzáadása
Egy igazi alkalmazásban általában egynél több szerkentyűre van szükséged. Helyezzünk egy QPushButtont a szövegdoboz alá. Ez arra szolgál majd, hogy ha a felhasználó rákattint, a program kilépjen.
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 becsatoljuk a QtGui headert, ami magában foglalja a Qt összes grafikus osztályát.
A tizedik sorban a Qt ( signál slot ) jel rés mechanizmusa segítségével lekezeljük a Kilépés gomb megnyomását.
A rés függvény a futás során hívódik meg a neve segítségével. A jelek olyan függvények, amelyek a megfelelő esemény bekövetkezésekor automatikusan meghívják a hozzájuk csatlakoztatott réseket. Esetünkben a quit() a szerkentyűnk egy beépített rése, amelyet meghívva az alkalmazás kilép. A gombunk clicked() jele pedig a gomb megnyomásakor lesz kibocsátva. A jel-rés hozzárendelést a statikus QObject::connect() 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 hozunk létre. Ahogy már említettük a szerkentyűk (szülő szerkentyűk) tartalmazhatnak további szerkentyűket (gyermek szerkentyűket). Megadhatjuk a gyermek szerkentyűk pontos méretet és helyzetét, de egyszerűbb, ha ehelyett (layoutokat) elrendezéseket használunk, így ezek kezelik majd a gyermekszerkentyűk elrendezését. A QVBoxLayout például a gyermek szerkentyűket egy függőleges oszlopba rendezi.
A 13. és 14. sorban hozzáadjuk a szövegdobozunkat és a nyomógombunkat az elrendezéshez, majd a 17. sorban érvénybe léptetjük az elrendezést.
További olvasnivalók:
|. Miről |. Hol | | Szignálok és Szlotok | Signals & Slots | | Layoutok | Layout Management, Widgets and Layouts, Layout Examples | | A QT beépített widgetkészlete | Qt Widget Gallery, Widget Examples |
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 osztályból származtatjuk a programfelület legfelsőbb osztályát, és létrehozunk egy rést, amihez hozzákötjük a Kilépés gomb kattintás jelé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ály kihírdetésének elején lennie. Ez a makró az osztályunkat QObjectként deklarálja (természetesen a használatához a QObjecttől kell származtatnunk). Ez a példánkban is így van, hiszen a QWidget osztály a QObjectből van származtatva. A QObject különféle funkciókkal bővíti ki a C++ osztályok tulajdonságait. Például az osztály és rések neve lekérdezhetővé válik futásidőben. Továbbá lehetőség van a rések argumentumainak típusát lekérdezni, illetve név alapján meghívni azokat.
A 9. sorban meghírdetjük a quit() rést a slots makró segítségével. A résünket ezután hozzáköthetjük bármilyen jelhez, amelynek nincs argumentuma.
A következőkben létrehozunk egy Notepad osztályt, amelynek a elem-felépítőjében ( constructor ) hozzuk létre a felületet, és kötjük össze a réseket a jelekkel. Ez a 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álunk a textEdit és a quitButton elérésére. Az ilyen grafikus elemeket mindig a ( heap -en ) halmon 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() 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 részletezzük, további információt a Qt Linguist 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, Writing Source Code for Translation, Hello tr() Example, Internationalization with Qt | | QObject és a Qt objektummodell-rendszere | Object Model | | qmake a Qt build rendszere | qmake Manual | ===
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 elrendezést ( layout ) tartalmaz, amelyre elhelyezhetjük saját menü sorunkat, eszköztárainkat, a kiköthető szerkentyűk számára rögzítési területet, illetve az állapotsort is. A QMainWindownak van egy középső területe, ahol elhelyezhetünk bármilyen szerkentyűt. 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 majd megvalósítunk két rést, mely a dokumentum megnyitására és mentésére fog szolgálni.
A fő ablakokban gyakran megesik az, hogy egy rést több szerkentyű 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 osztályt, amelyet átadhatunk több szerkentyűnek is, majd a jelét a megfelelő résekhez köthetjük. Például a QMenu és a QToolBar is létrehozhat menüket, eszköztárelemeket ugyanannak a QAction -nek a hatására.
Ahogyan már említettük, a grafikus elemeknek a Notepad osztály elem-felépítőjében adunk kezdőértéket.
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&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 elem-felépítőjében egy szöveget adunk meg argumentumként. Ez a szöveg fog megjelenni azokon a szerkentyűkön, amelyekhez rendeljük őket (esetünkben a menüelemeken). Ha ugyanazt a funkciót el szeretnénk érni az eszköztárunkról is, akkor a művelethez ( action ) jelképet ( icon ) is kell rendelnünk. Tehát, ha egy menüre rákattintunk, az majd bekapcsolja a műveletünket, amely ezáltal elküldi a triggered() jelét, amely meghívja a hozzákötött réseket.
További olvasnivalók:
|. Miről |. Hol | | Főablak és egyéb ablakok | Application Main Window, Main Window Examples | | MDI alkalmazások | QMdiArea, MDI Example |
A következő kódrészletben majd megvalósítjuk a mentés és megnyitás kezelésére szolgáló réseket.
Kezdjük az open() réssel:
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 pont e feladatra van egy osztály a QFileDialog , amely egy párbeszédablak 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 párbeszédablakot láthatjuk, ahogyan az KUbuntun megjelenik.
A getOpenFileName()) statikus metódus egy párbeszédablakot jelenít meg (az alkalmazás többi ablaka nem használható addig, 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 betűjelsort, 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() metódusával, amely igazzal tér vissza, ha a megnyitás sikerült. Most nem részletezzük a hibakezelés, de ha érdekel, utánanézhetsz ezeknek a További információ részben. Ha a fájl nem nyitható meg, akkor egy QMessageBox jelenítjük meg a hibaüzenetet. A részletekért lásd a QMessageBox osztály súgóját.
Az adatok beolvasása egyértelmű a QFile readAll() metódusának köszönhetően. Ez a függvény, egy a fájlban lévő adatokat tartalmazó QByteArray -jel tér vissza. A QByteArray constData() metódusa segítségével az adatokat const char* formában is elérhetjük, amit már átadhatunk a QString elem-felépítőnek. Így a fájl tartalma megjeleníthető a szövegdobozban. Végül a close() metódussal bezárjuk a fájlt, így adva vissza a fájl-leírót az operációs rendszernek.
Most, hogy megvagyunka megnyitás réssel, 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 objektumon keresztül írjuk vissza a fájlunkba. Ez az osztály mintegy ráépül a QFile objektumunkra, lehetővé téve, hogy a neki küldött szövegeket közvetlenül a fájlunkba írhassuk.
=== További olvasnivalók: |. Miről |. Hol | ===