Qt rajzolás munkafüzet Elemi Alkalmazások fejlesztése 3.
1. fejezet Impresszum Qt rajzolás munkafüzet (C)2006 Zimler Attila Tamás <hijaszu@hlfslinux.hu> Visszajelzéseket szivesen fogadok. A munkafüzet online formában a következ címen található: http://people.inf.elte.hu/hijaszu/qtdrawing/index.html A dokumentum generálásának dátuma: 2006. május 10.
2 Impresszum
2. fejezet Bevezet Formátumok class Example { /* Ez egy példa kódrészlet */ ; # Egy parancssori utasítás így néz ki (a # a prompt jel). függvény() Ez a jelölésmód azonban nem a függvény szignatúra helyes írásmódja! (El fordulhat, hogy van paramétere a függvénynek, de ez nem kerül kiírásra.) változó Ez egy változó jelölése. Az állományok jelölése ezen a módon lesz megvalósítva. Megjegyzések ˆ El fordulhat, hogy a Qt környezet speciális beállításokat igényel az adott gépen, a.pro állományban. Ehhez további segítség: http://people.inf.elte.hu/hijaszu/eaf3_- exercise3.html. Amennyiben így kell használni a Qt-t, akkor az összes "qmake -project" parancs kiadása után újra be kell állítani ezeket a speciális dolgokat a.pro állományban. ˆ A hosszabb programrészletekben az alábbi formátumú megjegyzések lesznek, ezeknek a helyzete nem változik, miután belekerültek a kódba. (Tehát ezekhez képest lehet viszonyítani, hogy milyen kódot hová kell írni, és ezért a kód változatlan részletei elhagyhatóak.) /* határolósor */ ˆ A harmadik feladatsortól kezdve mindegyik feladat után le lehet fordítani a programot és meg lehet nézni a futását (ezért nincs is már odaírva a feladatok megoldásához, hogy tegyük ezt meg). A fordítást a következ paranccsal tehetjük meg: # make
4 Bevezet
3. fejezet A Qt grakai rendszere A Qt grakai rendszere több komponens együttm ködéséb l áll. A graka során nem közvetlenül a rajzfelületre rajzolunk, hanem egy logikai térbe. A logikai tér a rajzfelületre több lépcs ben képz dik, nem feltétlenül az alábbi sorrendben (viszont az eredmény ugyanaz lesz). 1. A logikai tér koordinátái átalakításra kerülnek, így tetsz leges helyre helyezhetjük a logikai térben az origót. 2. A logikai tér egy transzformációs mátrix segítségével átalakításra kerül, így az ábrát kirajzolás el tt forgathatjuk és eltolhatjuk. 3.1. ábra. A Qt rajzolási rendszere. Ennek a rendszernek több el nye is van: ˆ Fix koordinátákat rakhatunk a rajzunkba, és az ablak átméretezésénél ez nem fog problémát okozni. ˆ Eltolhatjuk a rajz közepére az origót, ha az nekünk úgy kényelmes. ˆ Elforgathatjuk (akár többször is) a rajzfelületet a rajzolás el tt. Ebb l következik, hogy egy kényelmetlen szögben rajzolás helyett, bármilyen állapotban megrajzolhatjuk az ábrát. Ezután elforgatva az ábrát az eredmény az lesz, mintha a kényelmetlen szögben rajzoltunk volna (persze nehézkes számítások nélkül). ˆ A leképezésnek a logikai és a zikai rajzfelület között nem szükséges, hogy vízszintes és függ leges arányban is ugyanolyan arányú legyen.
6 A Qt grakai rendszere
4. fejezet A feladatsorozat célja A munkafüzetben a feladatsorok folyamán egy grakus óra programot fogunk létrehozni. A program a következ tulajdonságokkal fog rendelkezni: ˆ Az aktuális id t fogja mutatni a program. ˆ Az ablak átméretezésekor arányosan nagyítjuk a rajzot. ˆ Kiküszöböljük a villogást az ábrákon. 4.1. ábra. A cél
8 A feladatsorozat célja
5. fejezet Alap Qt program létrehozása 1. Hozzunk létre egy main() függvényt és fordítsuk le! Tipp Ne felejtsük el, hogy a Qt alkalmazás elindításához a main() függvény két paraméteres formájára lesz szükségünk. (a) Hozzuk létre az alábbi tartalmú main.cpp állományt: int main(int argc, char* argv[]) { (b) Állítsuk el a qmake.pro állományát: # qmake -project (c) Fordítsuk le a programot: # qmake # make 2. Hozzunk létre egy f ablakot és jelenítsük meg a main() függvényb l! (A f ablak osztályának a munkafüzet a MainWnd nevet adja.) Tippek (a) A következ fejléc állományokra lesz szükség: ˆ qmainwindow.h: a f ablak származtatásához. ˆ qapplication.h: a Qt f program létrehozásához. (b) A f ablak osztályának deklarációját (.h) és denícióját (.cpp) mindenképpen két külön állományba kell rakni, mert különben a qmake nem fog rendesen m ködni, ha a meta object compiler-t (moc) kell futtatnia. (c) Ne felejtsük el a Q_OBJECT makrót a f ablak osztályából. (d) Jelenleg elég ha a f ablak csak egy üres konstruktort tartalmaz. (e) Könnyen elérhetjük, hogy a f ablak becsukására a program megálljon, ha használjuk a QApplication::setMainWidget() metódusát. (f) Mivel extra állományokat adtunk a projekthez, ezért a projekt állományt aktuálizálni kell. Ezt két módon tehetjük meg:
10 Alap Qt program létrehozása ˆ a HEADERS konstanshoz hozzáadjuk az új fejléc állományokat, a SOURCES konstanshoz hozzáadjuk az új.cpp állományokat. Amennyiben bármelyik nem létezik, létrehozzuk. ˆ Újrageneráljuk a.pro állományt: # rm -f *.pro # qmake -project Megjegyzés: Ne felejtsük el a Makele állományt újragenerálni. # qmake (a) Hozzuk létre az alábbi tartalmú mainwnd.h állományt: #ifndef MAINWND_H #define MAINWND_H #include <qmainwindow.h> class MainWnd : public QMainWindow { Q_OBJECT public: MainWnd(); ; #endif /* MAINWND_H */ (b) Hozzuk létre az alábbi tartalmú mainwnd.cpp állományt: #include "mainwnd.h" MainWnd::MainWnd() { (c) A main.cpp állományt módosítsuk, hogy a következ képpen nézzen ki: #include "mainwnd.h" #include <qapplication.h> int main(int argc, char* argv[]) { QApplication app(argc, argv); MainWnd mw; mw.show(); app.setmainwidget(&mw); app.exec(); (d) Generáljuk újra a.pro állományt: # rm -f *.pro # qmake -project (e) Fordítsuk le a programot. # qmake # make 3. Hozzunk létre a QWidget osztályból származtatással egy egyedi widget-et és azt helyezzük el a f ablakon! (Ez az osztály a munkafüzetben a Clock nevet viseli.) Tippek (a) Ne felejtsük el, hogy a QWidget nem rendelkezik nulla paraméterszámú konstruktorral, hanem alapértelmezett értékei vannak a konstruktorának.
11 (b) A f ablak adattagjai közé mutató formában vegyük fel az újonnan létrehozott widget típust. (c) A QMainWindow::setCentralWidget() metódus segítségével rakhatjuk a f ablakra az objektumot. (d) Ne felejtsük el a f ablakot kiegészíteni egy destruktorral, ahol az egyedi widget objektumot megsemmisítjük. (e) Ne felejtsük el a Q_OBJECT makrót. (f) Ne felejtsük el módosítani a.pro állományt. (a) Hozzuk létre az alábbi clock.h állományt: #ifndef CLOCK_H #define CLOCK_H #include <qwidget.h> class Clock : public QWidget { Q_OBJECT public: Clock(QWidget* parent = 0, const char* name = 0, WFlags f = 0); ; #endif /* CLOCK_H */ (b) Hozzuk létre az alábbi clock.cpp állományt: #include "clock.h" Clock::Clock(QWidget* parent, const char* name, WFlags f) : QWidget(parent, name, f) { (c) Vegyünk fel egy privát _clock adattagot a MainWnd osztályba és szerkesszük be a clock.h fejlécállományt. Ennek eredményeképpen a következ képpen kell kinéznie a mainwnd.h állománynak: #ifndef MAINWND_H #define MAINWND_H #include <qmainwindow.h> #include "clock.h" class MainWnd : public QMainWindow { Q_OBJECT Clock* _clock; public: MainWnd(); ~MainWnd(); ; #endif /* MAINWND_H */ (d) Helyezzük a f ablakra az objektumot. Ehhez módosítsuk a MainWnd osztály konstruktorát: MainWnd::MainWnd() { setcentralwidget(_clock = new Clock(this));
12 Alap Qt program létrehozása (e) Írjuk meg a MainWnd osztály 3. pontjában már bevezetett destruktorát: MainWnd::~MainWnd() { delete _clock; (f) Generáljuk újra a.pro állományt és fordítsuk le a programot: # rm -f *.pro # qmake -project # qmake # make
6. fejezet A rajzolást végz kód el készítése 1. Hozzunk létre egy _draw() metódust a Clock osztály számára! (a) Módosítsuk a clock.h állományt, hogy a következ képpen nézzen ki: #ifndef CLOCK_H #define CLOCK_H #include <qpainter.h> #include <qwidget.h> // új sor class Clock : public QWidget { Q_OBJECT void _draw(qpainter* painter); // új sor public: Clock(QWidget* parent = 0, const char* name = 0, WFlags f = 0); ; #endif /* CLOCK_H */ (b) A clock.cpp állományban hozzuk létre a következ metódust _draw() metódust: void Clock::_draw(QPainter* painter) { /* Változók deklarálása */ /* Az alap megrajzolása */ /* A vonalak megrajzolása */ /* A számok elhelyezése az óralapon */ /* A nagymutató megrajzolása */ /* A kismutató megrajzolása */ /* A másodperc mutató megrajzolása */ /* Újabb frissítés ütemezése */ Megjegyzés: A _draw() implementációját a következ fejezetekben adjuk meg, most csak a gerincét hozzuk létre. (c) Fordítsuk le a programot. # make 2. Deniáljuk felül a Clock osztályban a QWidget::paintEvent() metódusát, és ebb l hívjuk meg a _draw() metódust! Tippek
14 A rajzolást végz kód el készítése (a) Hozzuk létre a QPainter objektumot. (b) Válasszuk ki a kisebbik méretet, hogy arányosan tudjuk megjeleníteni a rajzot. (c) Állítsuk be a koordinátarendszert. (d) Hívjuk meg a rajzolást végz rutint (_draw()). (a) Módosítsuk a clock.h állományt úgy, hogy a következ képpen nézzen ki: #ifndef CLOCK_H #define CLOCK_H #include <qpainter.h> #include <qwidget.h> class Clock : public QWidget { Q_OBJECT void _draw(qpainter* painter); void paintevent(qpaintevent* event); // új sor public: Clock(QWidget* parent = 0, const char* name = 0, WFlags f = 0); ; #endif /* CLOCK_H */ (b) Valósítsuk meg a következ Clock::paintEvent() metódust: void Clock::paintEvent(QPaintEvent*) { /* Kett s pufferelés el készítés */ /* A QPainter objektum létrehozása */ QPainter painter(this); /* A rajzoló rutin meghívása */ int side = QMIN(width(), height()); painter.setviewport( (width() - side) / 2, (height() - side) / 2, side, side ); painter.setwindow(-50, -50, 101, 101); _draw(&painter); /* A kett s pufferelés ábrájának kihelyezése */ (c) Fordítsuk le a kódot: # make
7. fejezet A rajzolást megvalósító kód 1. Rajzoljuk meg az óra alapját! Tippek (a) Állítsuk be a ceruzát fehérre. (b) Állítsuk be a kitöltést fehérre. (c) Rajzoljuk meg a kört a QPainter::drawEllipse() metódussal. (a) Írjuk át a Clock::_draw() metódus fejlécét a clock.cpp állományban, hogy a következ módon nézzen ki: void Clock::_draw(QPainter* painter) (b) Adjuk hozzá a Clock::_draw() metódushoz a következ részletet: /* Az alap megrajzolása */ painter->setpen(qpen(white, 1, SolidLine)); painter->setbrush(qbrush(white, SolidPattern)); painter->drawellipse(-50, -50, 101, 101); /* A vonalak megrajzolása */ 2. Húzzuk meg a 12 óra értékhez tartozó függ leges vonalat! Tippek (a) Állítsuk a ceruzát feketére. (b) Húzzuk meg a vonalat a QPainter::drawLine() metódussal. Illesszük a következ kódot a Clock::_draw() metódusba: /* A vonalak megrajzolása */ painter->setpen(qpen(black, 1, SolidLine)); painter->drawline(0, -50, 0, -47); /* A számok elhelyezése az óralapon */
16 A rajzolást megvalósító kód 3. Rajzoljuk meg az összes vonalat! Tippek (a) Vegyük fel egy QWMatrix típusú objektumot a Clock::_draw() metódusba. (b) Ismételjük meg 60-szor a következ három lépést: i. Húzzunk egy vonalat, ahogy azt az el z feladatban tettük (pontosan ugyanazokkal a koordinátákkal). ii. Forgassuk a QWMatrix objektumot 6 fokkal. iii. Állítsuk be a módosított QWMatrix objektum segítségével a QPainter world- Matrix-át ( QPainter::setWorldMatrix()). (a) Vegyünk fel egy QWMatrix típusú mátrixot a Clock::_draw() metódusba: /* Változók deklarálása */ QWMatrix matrix; /* Az alap megrajzolása */ (b) Alakítsuk át a vonalak rajzolását a következ re: /* A vonalak megrajzolása */ for (int i = 0; i < 60; ++i) { painter->setpen(qpen(black, 1, SolidLine)); painter->drawline(0, -50, 0, -47); matrix.rotate(6); painter->setworldmatrix(matrix); /* A számok elhelyezése az óralapon */ 4. Legyen minden ötödik vonal vastagabb és hosszabb! Alakítsuk át a Clock::_draw() metódusát a következ módon: /* A vonalak megrajzolása */ for (int i = 0; i < 60; ++i) { // vastag vagy vékony vonal kell? painter->setpen(qpen(black, i % 5 == 0? 3 : 0, SolidLine)); // rövid vagy hosszú vonal kell? painter->drawline(0, -50, 0, i % 5 == 0? -45 : -47); // 6 fokonként egy-egy vonal, összesen 60 vonal. matrix.rotate(6); painter->setworldmatrix(matrix); /* A számok elhelyezése az óralapon */ 5. Helyezzük el a 12-es feliratot az óralapon! Tippek
17 (a) A QPainter::drawText() metódusai között van egy olyan, amelynek meg lehet adni a befoglaló négyzeten belül a szöveg igazitását. (b) A QString típusnak van egy setnum() metódusa, aminek segíségével egy számot könnyen szöveggé lehet alakítani. (c) Körülményes végiggondolni, hogy az el z feladat megoldása során a QPainter world- Matrix tulajdonsága milyen állapotban maradt. Egyszer bb lehet alaphelyzetbe állítani. Alakítsuk a következ re a Clock::_draw() metódust: /* A számok elhelyezése az óralapon */ QString text; matrix.reset(); painter->setworldmatrix(matrix); text.setnum(12); painter->setpen(qpen(blue, 0, SolidLine)); painter->drawtext( -10, -45, 20, 20, Qt::AlignHCenter Qt::AlignVCenter, text ); /* A nagymutató megrajzolása */ 6. Helyezzük fel az összes számot! Tipp A QWMatrix::map() metódus segítségével koordinátákat transzformálhatunk a logikai térben. A Clock::_draw() megfelel részlete: /* A számok elhelyezése az óralapon */ QString text; matrix.reset(); painter->setpen(qpen(blue, 0, SolidLine)); painter->setworldmatrix(matrix); const int cx = 0; // x irányú közepe a szövegnek const int cy = -35; // y irányú közepe a szövegnek const int tw = 10; // A szöveg szélessége (valójában / 2) const int th = 10; // A szöveg magassága (valójában / 2) for (int i = 3; i < 13; i += 3) { int tcx, tcy; // átalakított cx, cy matrix.rotate(90); matrix.map(cx, cy, &tcx, &tcy); text.setnum(i); painter->drawtext( tcx - tw, tcy - th, tw * 2, th * 2, Qt::AlignHCenter Qt::AlignVCenter, text ); /* A nagymutató megrajzolása */
18 A rajzolást megvalósító kód 7. Hozzunk létre a Clock osztály számára egy _drawarrow() metódust, amely paraméterben megkapja a QPainter objektumot és a mutató hosszát! Ezután rajzoljuk meg a mutatót és a mutató hegyét! (a) Az új clock.h állomány tartalma: #ifndef CLOCK_H #define CLOCK_H #include <qpainter.h> #include <qwidget.h> class Clock : public QWidget { Q_OBJECT void _draw(qpainter* painter); void _drawarrow(qpainter* painter, int length); // új sor void paintevent(qpaintevent* event); public: Clock(QWidget* parent = 0, const char* name = 0, WFlags f = 0); ; #endif /* CLOCK_H */ (b) A Clock::_drawArrow() metódus: void Clock::_drawArrow(QPainter* painter, int length) { /* A ceruza és az ecset beállítása */ painter->setpen(qpen(black, 1, SolidLine)); painter->setbrush(qbrush(black, SolidPattern)); /* A mutató hegyének megrajzolása */ QCOORD triangle[3][2] = { { -3, -length + 10, { 0, -length, { 3, -length + 10 ; painter->drawconvexpolygon(qpointarray(3, &triangle[0][0])); /* A mutató szárának megrajzolása */ (c) A Clock::_draw() metódus szükséges módosítása: /* A nagymutató megrajzolása */ matrix.reset(); painter->setworldmatrix(matrix); _drawarrow(painter, 45); /* A kismutató megrajzolása */ 8. Hozzuk létre a mutató szárát. Tipp Rajzoljuk meg a kört a mutató szárának végére, hogy szépen nézzen ki. Alakítsuk át a következ re a Clock::_drawArrow() metódust: /* A mutató szárának megrajzolása */ QCOORD box[4][2] = { { -1, -length + 10, { 1, -length + 10, { 1, 0, { -1, 0
19 ; painter->setpen(qpen(black, 1, SolidLine)); painter->setbrush(qbrush(black, SolidPattern)); painter->drawconvexpolygon(qpointarray(4, &box[0][0])); painter->drawellipse(-1, -1, 3, 3); 9. Rajzoljuk meg a kismutatót. A Clock::_draw() metódust kell módosítani: /* A kismutató megrajzolása */ matrix.reset(); painter->setworldmatrix(matrix); _drawarrow(painter, 30); /* A másodperc mutató megrajzolása */ 10. Rajzoljuk meg a másodperc mutatót. A Clock::_draw() metódusának szükséges módosítása: /* A másodperc mutató megrajzolása */ matrix.reset(); painter->setworldmatrix(matrix); painter->setpen(qpen(red, 1, SolidLine)); painter->drawline(0, -45, 0, 0); /* Újabb frissítés ütemezése */
20 A rajzolást megvalósító kód
8. fejezet Az aktuális id t beállító kód 1. Valósítsuk meg a nagymutató beállítását! Tippek (a) A worldmatrix forgatásával nagyon könnyen megfelel irányba lehet állítani a mutatót. (b) A QTime::currentTime() metódusával le lehet kérdezni a megfelel id t. (a) Szerkesszük be a qdatetime.h fejlécet a clock.cpp-be: #include <qdatetime.h> (b) Módosítsuk a következ két részletet a Clock::_draw() metódusban: /* Változók deklarálása */ QWMatrix matrix; QTime t = QTime::currentTime(); /* Az alap megrajzolása */ /* A nagymutató megrajzolása */ matrix.reset(); matrix.rotate(t.minute() * 6); painter->setworldmatrix(matrix); _drawarrow(painter, 45); // új sor /* A kismutató megrajzolása */ 2. Valósítsuk meg óra és a másodperc mutató beállítását! Szükséges módosítás a Clock::_draw() állományban. /* A kismutató megrajzolása */ matrix.reset(); matrix.rotate((t.hour() * 60 + t.minute()) / 2); painter->setworldmatrix(matrix); _drawarrow(painter, 30); // új sor /* A másodperc mutató megrajzolása */
22 Az aktuális id t beállító kód matrix.reset(); matrix.rotate(t.second() * 6); painter->setworldmatrix(matrix); painter->setpen(qpen(red, 1, SolidLine)); painter->drawline(0, -45, 0, 0); // új sor /* Újabb frissítés ütemezése */ 3. Kapcsoljuk egy id zít re az újrarajzolást! Tippek (a) Vegyünk fel egy QTimer adattagot a Clock osztályba. (b) A rajzolás végeztével egy egyszeri lefutású id zít t indítsunk 1 másodperces késleltetéssel. Hogy miért? Mert így amikor a rendszer újrarajzolja az objektumot, akkor elölr l kezd dik az egy másodperc mérése. (c) Az id zít lejártát az update() metódusra kapcsolhatjuk. (d) Amennyiben új adattagot veszünk fel az osztályba, akkor a qmake által generált Makele ezt nem tudja teljesen helyesen értékelni. # make distclean # make (a) A clock.h új tartalma: #ifndef CLOCK_H #define CLOCK_H #include <qpainter.h> #include <qtimer.h> #include <qwidget.h> class Clock : public QWidget { Q_OBJECT QTimer timer; // új sor void _draw(qpainter* painter); void _drawarrow(qpainter* painter, int length); void paintevent(qpaintevent* event); public: Clock(QWidget* parent = 0, const char* name = 0, WFlags f = 0); ; #endif /* CLOCK_H */ (b) A szükséges módosítás a Clock::_draw() metódusban: /* Újabb frissítés ütemezése */ connect(&timer, SIGNAL(timeout()), this, SLOT(update())); timer.start(1000, true); (c) Amennyiben új adattagot veszünk fel az osztályba, akkor a qmake által generált Makele ezt nem tudja teljesen helyesen értékelni. # make distclean # make 4. Indítsuk el a programot, nagyítsuk fel teljes képerny sre és gyeljük meg, ahogy villog.
9. fejezet A villogás kiküszöbölése kett s puerelés (double buering) segítségével Mi is az a kett s puerelés? A villogást a rajz folyamatos újrarajzolása során a számítások viszonylagos lassúsága okozza. (Ez a számítás a képerny frissítéséhez képest értend.) A kett s puerelés ezt úgy oldja meg, hogy nem közvetlenül a képerny memóriaterületére rajzolunk. Amikor elkészülünk a rajzzal, akkor egy nagyon gyors rutinnal kicseréljük a képerny n látható rajzot a háttérben elkészülttel. Az, hogy ez hogy történik a rendszer ügyességén és hardverén múlik: ˆ Ha a grakus kártya rendelkezik kell en sok memóriával, és egy egész képerny nyi képr l van szó, akkor egy egyszer memóriacím átírással meg lehet ezt oldani. ˆ A DMA segítségével a CPU-tól függetlenül lehet adatot mozgatni (közben a CPU számításokat végezhet). Megjegyzés: Ez a feladatsor csak a végén ad vizsgálható eredményt, függetlenül attól, hogy mindegyik lépés után lefordítható. 1. Emlékeztet az el z feladatsor végér l: Indítsuk el a programot, nagyítsuk fel teljes képerny sre és gyeljük meg, ahogy villog. 2. Hozzunk létre egy képet, majd méretezzük az aktuális objektumnak megfelel méret re! (Szükség lesz ehhez arra is, hogy a Clock::paintEvent() paraméterét nevesítsük, hogy elérjük.) (a) A qpixmap.h fejlécet be kell szerkeszteni a clock.cpp állományba. (b) A Clock::paintEvent() megfelel részlete: void Clock::paintEvent(QPaintEvent* event) { /* Kett s pufferelés el készítés */ static QPixmap pixmap; // módosított sor!
24 A villogás kiküszöbölése kett s puerelés (double buering) segítségével QRect rect = event->rect(); QSize newsize = rect.size().expandedto(pixmap.size()); pixmap.resize(newsize); pixmap.fill(this, rect.topleft()); /* A QPainter objektum létrehozása */ 3. Módosítsuk a QPainter objektum létrehozását, hogy a QPixmapre rajzoljon! A Clock::paintEvent() metódus megfelel részlete: /* A QPainter objektum létrehozása */ QPainter painter(&pixmap, this); // módosított sor! /* A rajzoló rutin meghívása */ 4. A kett s puerelés képét helyezzük ki az objektumra! A Clock::paintEvent() metódus vége: /* A kett s pufferelés ábrájának kihelyezése */ bitblt(this, event->rect().topleft(), &pixmap); 5. Vegyük át a QWidget-t l az objektum teljes rajzolását (kapcsoljuk ki az automatikus újrarajzolási eseményeket)! Megjegyzés: Erre azért van szükség, mert különben automatikusan letörli az objektumot a rendszer. Módosítsuk a Clock::Clock() konstruktorát, hogy a következ módon nézzen ki: Clock::Clock(QWidget* parent, const char* name, WFlags f) : QWidget(parent, name, f Qt::WNoAutoErase) { 6. Fordítsuk le a kódot és gyeljük meg, hogyha odébb mozgatjuk az ablakot, akkor egy másodpercig szétesik a kép! 7. Oldjuk meg, hogy ha megmozdítjuk az ablakot, akkor se essen szét a kép! Tipp A QMainWindow::moveEvent() metódusát kell felüldeniálni. (a) A mainwnd.h új verziója: #ifndef MAINWND_H #define MAINWND_H #include <qmainwindow.h> #include "clock.h" class MainWnd : public QMainWindow {
25 Q_OBJECT Clock* _clock; void moveevent(qmoveevent*); public: MainWnd(); ~MainWnd(); ; #endif /* MAINWND_H */ // új sor (b) És a MainWnd::moveEvent() metódus megvalósítása: void MainWnd::moveEvent(QMoveEvent*) { _clock->update();