A Rajzolás lap A rajzolás lap elemi rajzolási lehetőségek bemutatására szolgál. A rajzolás a jobboldali pnlright widget egyik lapjára rakott widgetre történik. A pnlright egy több lapot tartalmazó widget a Stacked Widget, ami hasonlóan a QToolBox-hoz több lap megjelenítésére képes, de a lapjainak nincs fejléce. A Rajzolás lap az első (0 indexű) oldalra fog dolgozni. A jobboldalon a pnlright egy Stacked Widget Állítsuk be az első lapot és nevezzük el pnldraw-ra: Amikor a Tool Box-on egy fejlécet kiválasztunk az a currentchanged(int index) SIGNAL-t küldi el. Ennek lekezeléséhez adjuk hozzá a megfelelő függvény deklarációt a header fájlhoz: void on_pnxmenu_currentchanged(int index); A cpp fájlhoz pedig a definícióját: void GrafikaQTvel::on_tbxMenu_currentChanged(int index) if (index >= 0) if (index == 1) ui.pnlright->setcurrentindex(0); Azért ilyen bonyolult, mert ugyanazt a lapot szeretnénk több menüben is felhasználni, így nem lehet egyszerűen. ui.pnlright->setcurrentindex(index);-et használni. Ezután térhetünk rá a működtetésre. Még a tényleges rajzolás előtt intézzük el a beviteli mezőket! Egy jó programban az egyes mezők ezen a lapon csak akkor aktívak sőt esetleg csak akkor láthatóak, ha a megfelelő rajzolási lehetőség van kiválasztva. Arról is gondoskodni kell, hogy az egyes mezőkbe csak érvényes adatokat írhassunk be. Ehhez a megfelelő SLOT-ok függvényeit kell elkészíteni. A rádiógombokhoz a toggled(bool), a jelölőnégyzethez statechanged(int) a gombokhoz a
clicked(), a beviteli mezőkhöz a textchanged(qstring) SIGNAL-okat kell lekezelni. Ezek deklarációi a grafikaqtvel.h fájlban: void on_rbfreedraw_toggled(bool); void on_rbline_toggled(bool); void on_rbrectangle_toggled(bool); void on_rbtriangle_toggled(bool); void on_rbellipse_toggled(bool); void on_rbpolygon_toggled(bool); void on_rbcircle_toggled(bool); void on_chkfill_statechanged(int state); void on_btncleardatar_clicked(); void on_edtx1_textchanged (QString); void on_edty1_textchanged (QString); void on_edtw1_textchanged (QString); void on_edth1_textchanged (QString); Az egyes beviteli mezők lekezelésénél ügyelni kell arra, hogy éppen melyik rádiógomb van kijelölve. Az rbfreedraw állapota megváltozásának lekezelése: void GrafikaQTvel::on_rbFreeDraw_toggled(bool b) if (b) // cask ha ez van bejelölve ui.btndraw->setenabled(false); // nem kell a gombot benyomni a használathoz ui.canvas->startfreehanddrawing(); Nem keel egyik beviteli menu sem, elrejtjük őket else ui.edtx1->setvisible(false); ui.edty1->setvisible(false); ui.edtw1->setvisible(false); ui.edth1->setvisible(false); ui.canvas->stopfreehanddrawing(); A többi rádiógombnál a beviteli mezők közül mindazokat láthatóvá tesszük amelyekre szükség van. Ezek szövegeit is át kell írjuk. Sajnos a Qt-ben van egy kis hiba, ami miatt a Windows alatt Visual Studio-ban írt programoknál az ékezetes betűk néha hibásan jelennek meg. Ez egy példája annak, hogy még ma is gond van az egyes országok speciális betűjeivel.
Ez a hiba akkor fordul elő, amikor olyan betűket talál a szerkesztő, amiket a Windows-os kódlapon nem tud elmenteni. Ilyenkor a Windows felajánlja az oldalt elmenthetjük UTF-8 kódolással. Az UTF-8 fájlok elejéhez a szerkesztő hozzáragaszt egy Byte Order Mark (BOM) karakter sorozatot. Semmilyen UTF-8-at ismerő programnak nem szabad ezt megjelenítenie, át kell ezt ugrania. Valamiért a Qt Windows alatti fordításánál ez bezavar és a kiírt szövegben az UTF-8 kódok rosszul jelennek meg. A BOM-ra azonban nincs valójában szükség, ezért ha levágjuk a fájl elejéről a BOM byte-jait 1 akkor a lefordított programban a szöveg már hibátlan lesz. Ezután, amennyiben a fájl éppen meg volt nyitva a szerkesztőben, a VS felajánlja, hogy betölti a módosított fájlt. Fogadjuk ezt el! De ha módosítjuk, majd újra elmentjük a fájlt a VS-ből, akkor a BOM újra vissza kerül és ezt az eljárást újra el kell végezzük. Azt, hogy egy beviteli mezőben van-e valami beírva az isempty() függvénnyel nézhetjük meg. Rajzolni csak akkor szabad majd, ha minden szükséges beviteli mezőben van szám A többi beviteli mező függvényei ennek a fájlnak a végén megtalálhatóak. A rajzolás A rajzolást magát egy általunk készített widget kezeli, amit a festők vásznáról Canvas-nak neveztük el. Részletes leírása egy másik fájlban található, itt csak a használatáról beszélünk. A Canvas widget-re rajzolhatunk mindenféle vonalas ábrákat. Rajzolhatunk rá szabadkézzel, illetve megadott alakzatokat. A GrafikaQTvel program számára a Canvas program interfésze az érdekes csak. Ez a következő függvényeket jelenti: Canvas(QWidget *parent = 0); virtual ~Canvas() ; void StartFreeHandDrawing() _freehand = true; void StopFreehandDrawing() _freehand & false; // double buffer // lekérdezés bool IsModified() const return _modified; bool IsDrawing() const return _drawing; const QPoint &LastPos() const return _lastpoint; QColor GetPixel(const QPoint &pt); QColor PenColor() const return _pencolor; 1 Legegyszerűbb beolvasni a fájlt a Notepad++ szerkesztőbe és átírni a kódolását UTF-8 BOM-al ról UTF-8 ra, majd elmenteni.
int PenWidth() const return _penwidth; Qt::PenStyle PenStyle() const return _penstyle; Qt::PenCapStyle PenCapStyle() const return _pencap; Qt::PenJoinStyle PenJoinStyle()const return _penjoin; Qt::BrushStyle BrushStyle() const return _brushstyle; // Beállítás void SetPenWidth(int width) _penwidth = width; void SetPenColor(QColor color) _pencolor = color; void SetPenStyle (Qt::PenStyle &v) _penstyle= v; void SetPenCapStyle(Qt::PenCapStyle &v) _pencap= v; void SetPenJoinStyle(Qt::PenJoinStyle &v) _penjoin= v; void SetBrushStyle(Qt::BrushStyle &v) _brushstyle= v; // rajzolás void SetPixel(const QPoint &pt, QColor color); void FreeHand(); void LineTo(const QPoint &endpoint); void DrawEllipse(const QRect &rect); void DrawRect(const QRect & rect); void DrawFillRect(const QRect & rect); void DrawArc(double start, double end); void Clear(); // egy pont kirajzolása
Függelék grafikaqtve.h #ifndef GRAFIKAQTVEL_H #define GRAFIKAQTVEL_H #include <QtWidgets/QMainWindow> #include <QColor> #include "ui_grafikaqtvel.h" #include "canvas.h" class GrafikaQTvel : public QMainWindow Q_OBJECT public: GrafikaQTvel(QWidget *parent = 0); ~GrafikaQTvel(); void Parameters(); private: Ui::GrafikaQTvelClass ui; bool _busy = false; // gombokhoz használjuk // közös paraméterek Toll és Ecset lap RajzParameterek _params; // állapotok beolvasása után az egyes widgetek // adatait beállító függvények void _SaveState(); void _ReadState(); void _SetupControls(); // közös paraméterek Toll és Ecset lap void _SetupCommon(); // többi lap // Rajzolás int _usededitcnt = 0; void _SetupDrawing(); // ennyi edtx1, stb kell a Rajz gombokhoz // az egyes rádiógombok állítják be void _EnableDrawing(int edtcnt); // edtcnt = 1 - edtx1,,2 - edtx1 & edtx2,3 - edtx1 & edtx2 & edtw1,4 - edtx1 & edtx2 & edtw1 & edth1 void _AnyEditChanged(); // enable/disable rajz gomb // Grafika void _SetupGraph(); // Grafika void _SetupInteract(); // Fraktál void _SetupFractal(); void _SetupTransform(); void _SetupShapes(); void _SetupPictures();
void _SetupFilters(); private slots: void on_tbxmenu_currentchanged(int index); // közös paraméterek void on_sbpenwidth_valuechanged(int); void on_cbpenstyle_currentindexchanged(int index); void on_cbpencap_currentindexchanged(int index); void on_cbpenjoin_currentindexchanged( int index); void on_cbbrushstyle_currentindexchanged(int index); void on_btnpencolor_clicked(); void on_btnbrushcolor_clicked(); // rajzolás lap void on_btnclearcanvas_clicked(); void on_rbfreedraw_toggled(bool); void on_rbline_toggled(bool); void on_rbrectangle_toggled(bool); void on_rbtriangle_toggled(bool); void on_rbellipse_toggled(bool); void on_rbpolygon_toggled(bool); void on_rbcircle_toggled(bool); void on_chkfill_statechanged(int state); void on_btncleardatar_clicked(); void on_btndraw_clicked(); void on_edtx1_textchanged(qstring); void on_edty1_textchanged(qstring); void on_edtw1_textchanged(qstring); void on_edth1_textchanged(qstring); ; #endif // GRAFIKAQTVEL_H grafikaqtvel.cpp #include "grafikaqtvel.h" #include <QSettings> #include <QColorDialog> GrafikaQTvel::GrafikaQTvel(QWidget *parent) : QMainWindow(parent) ui.setupui(this); _ReadState(); // beállítja a canvas paramétereket is _SetupControls(); // beállítja a widgetek értékeit // Ha nem mentettük el az egyes lapok tartalmát, akkor // mindig szabadkézi rajzolással tudjuk kezdeni ui.rbfreedraw->toggled(true); ui.canvas->startfreehanddrawing(); GrafikaQTvel::~GrafikaQTvel()
_SaveState(); void GrafikaQTvel::_SaveState() QSettings settings("programozás 3", "GrafikaQtvel"); // A geometria settings.begingroup("ablak"); settings.setvalue("geometry", savegeometry()); settings.setvalue("state", savestate()); settings.endgroup(); // Közös rajzolási beállítások: settings.begingroup("toll"); settings.setvalue("vastagság", _params.penwidth); settings.setvalue("szín", _params.pencolor); settings.setvalue("stílus", (int)_params.penstyle); settings.setvalue("vonalvég", _params.pencap); settings.setvalue("kapcsolódás", _params.penjoin); settings.endgroup(); settings.begingroup("ecset"); settings.setvalue("szín", _params.brushcolor); settings.setvalue("stílus", (int)_params.brushstyle); settings.endgroup(); // Egyéb paraméterek elmentése void GrafikaQTvel::_ReadState() QSettings settings("programozás 3", "GrafikaQtvel"); // A geometria settings.begingroup("ablak"); restoregeometry(settings.value("geometry").tobytearray()); restorestate(settings.value("state").tobytearray()); settings.endgroup(); int iv; settings.begingroup("toll"); _params.penwidth=settings.value("vastagság", 1).toInt(); //1: default // Mival a QColor nem QVariant _params.pencolor = settings.value("szín", 0).value<QColor>(); _params.penstyle = (Qt::PenStyle)settings.value("Stílus", (int)qt::solidline).toint(); _params.pencap = (Qt::PenCapStyle)settings.value("Vonalvég", Qt::FlatCap).toInt(); _params.penjoin = (Qt::PenJoinStyle)settings.value("Kapcsolódás", Qt::MiterJoin).toInt();
settings.endgroup(); settings.begingroup("ecset"); _params.brushcolor = settings.value("szín", 0xFFFFFF).value<QColor>(); _params.brushstyle = (Qt::BrushStyle)settings.value("Stílus", (int)qt::nobrush).toint(); settings.endgroup(); // Egyéb paraméterek beolvasása ui.canvas->setparameters(_params); // A beolvasott adatok alapján beállítjuk az egyes // gombokat, Combo BOx-okat és a mezők tartalmát void GrafikaQTvel::_SetupControls() _SetupCommon(); // toll és ecset lap _SetupDrawing(); // rajzolás lap _SetupGraph(); _SetupInteract(); _SetupFractal(); _SetupTransform(); _SetupShapes(); _SetupPictures(); _SetupFilters(); // közös paraméterek Toll és Ecset lap void GrafikaQTvel::_SetupCommon() ui.sbpenwidth->setvalue(_params.penwidth); ui.cbpenstyle->setcurrentindex(_params.penstyle); ui.cbpencap->setcurrentindex(_params.pencap); ui.cbpenjoin->setcurrentindex(_params.penjoin); ui.cbbrushstyle->setcurrentindex(_params.brushstyle); ui.btnpencolor->setstylesheet("background:" + _params.pencolor.name()); ui.btnbrushcolor->setstylesheet("background:" + _params.brushcolor.name()); // TODO: többi lap egyelőre nem írtuk meg void GrafikaQTvel::_SetupDrawing() void GrafikaQTvel::_SetupGraph() void GrafikaQTvel::_SetupInteract() void GrafikaQTvel::_SetupFractal() void GrafikaQTvel::_SetupTransform() void GrafikaQTvel::_SetupShapes() void GrafikaQTvel::_SetupPictures() void GrafikaQTvel::_SetupFilters() // SLOT-ok void GrafikaQTvel::on_tbxMenu_currentChanged(int index)
if (index >= 0) if (index == 1) ui.pnlright->setcurrentindex(0); // common void GrafikaQTvel::on_sbPenWidth_valueChanged(int val) _params.penwidth = val; ui.canvas->setparameters(_params); // frissítés void GrafikaQTvel::on_cbPenStyle_currentIndexChanged(int index) _params.penstyle = (Qt::PenStyle)index; ui.canvas->setparameters(_params); // frissítés void GrafikaQTvel::on_cbPenCap_currentIndexChanged(int index) _params.pencap = (Qt::PenCapStyle)index; ui.canvas->setparameters(_params); // frissítés void GrafikaQTvel::on_cbPenJoin_currentIndexChanged(int index) _params.penjoin = (Qt::PenJoinStyle)index; ui.canvas->setparameters(_params); // frissítés void GrafikaQTvel::on_cbBrushStyle_currentIndexChanged(int index) _params.brushstyle = (Qt::BrushStyle)index; ui.canvas->setparameters(_params); // frissítés void GrafikaQTvel::on_btnPenColor_clicked() QString qs = ui.btnpencolor->stylesheet(); // a szöveg: background:#rrggbb alakú QColor col = QColor(qs.mid(qs.indexOf(":"))); col = QColorDialog::getColor(col, this, "Válassz toll színt!"); if (col.isvalid()) // egyébként az "Elvet" volt megnyomva _params.pencolor = col; ui.btnpencolor->setstylesheet("background:" + col.name()); ui.canvas->setparameters(_params); // frissítés
void GrafikaQTvel::on_btnBrushColor_clicked() QString qs = ui.btnbrushcolor->stylesheet(); // a szöveg: background:#rrggbb alakú QColor col = QColor(qs.mid(qs.indexOf(":"))); col = QColorDialog::getColor(col, this, "Válassz ecset színt!"); if (col.isvalid()) // egyébként az "Elvet" volt megnyomva _params.brushcolor = col; ui.btnbrushcolor->setstylesheet("background:" + col.name()); ui.canvas->setparameters(_params); // frissítés // rajzol void GrafikaQTvel::on_btnClearCanvas_clicked() ui.canvas->clear(); void GrafikaQTvel::on_btnDraw_clicked() int x1 = ui.edtx1->text().toint(), y1 = ui.edty1->text().toint(), x2 = ui.edtw1->text().toint(), y2 = ui.edth1->text().toint(); if (ui.rbline->ischecked()) x2 += x1; y2 += y1; ui.canvas->drawline(qpoint(x1, y1), QPoint(x2, y2)); else if (ui.rbrectangle->ischecked()) ui.canvas->drawrect(qrect(x1, y1, x2, y2), ui.chkfill ->ischecked()); else if (ui.rbellipse->ischecked()) ui.canvas->drawellipse(qrect(x1, y1, x2, y2), ui.chkfill ->ischecked()); else if(ui.rbcircle->ischecked()) ui.canvas->drawellipse(qrect(x1, y1, x2, x2), ui.chkfill ->ischecked()); else if (ui.rbtriangle->ischecked())
ui.canvas->drawtriangle(qpoint(x1,y1), x2, ui.chkfill ->ischecked()); else if (ui.rbpolygon->ischecked()) ui.canvas->drawpolygon(qpoint(x1, y1), x2, y2, ui.chkfill ->ischecked()); void GrafikaQTvel::on_rbFreeDraw_toggled(bool b) if (b) ui.btndraw->setenabled(false); ui.canvas->startfreehanddrawing(); ui.edtx1->setvisible(false); ui.edty1->setvisible(false); ui.edtw1->setvisible(false); ui.edth1->setvisible(false); else ui.canvas->stopfreehanddrawing(); // Enable/disable Rajz gomb void GrafikaQTvel::_EnableDrawing(int edtcnt) bool b = false; switch (edtcnt) // trükk: nincs break! case 4: b = ui.edth1->text().isempty(); case 3: b = ui.edtw1->text().isempty(); case 2: b = ui.edty1->text().isempty(); case 1: b = ui.edtx1->text().isempty(); break; default: break; ui.btndraw->setenabled(!b); void GrafikaQTvel::on_rbLine_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 4); ui.lbldrawwidth->settext("x2"); ui.lbldrawheight->settext("y2");
ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(true); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true); ui.edth1->setvisible(true); void GrafikaQTvel::on_rbRectangle_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 4); ui.lbldrawwidth->settext("szélesség"); ui.lbldrawheight->settext("magasság"); ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(true); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true); ui.edth1->setvisible(true); void GrafikaQTvel::on_rbTriangle_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 3); ui.lbldrawwidth->settext("oldalhossz:"); ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(false); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true); ui.edth1->setvisible(false); void GrafikaQTvel::on_rbEllipse_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 4); ui.lbldrawwidth->settext("szélesség"); ui.lbldrawheight->settext("magasság"); ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(true); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true);
ui.edth1->setvisible(true); void GrafikaQTvel::on_rbPolygon_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 4); ui.lbldrawwidth->settext("oldalhossz"); ui.lbldrawheight->settext("oldalszám"); ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(true); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true); ui.edth1->setvisible(true); void GrafikaQTvel::on_rbCircle_toggled(bool b) if (b) _EnableDrawing(_usedEditCnt = 3); ui.lbldrawwidth->settext("sugár"); ui.lbldrawwidth->setvisible(true); ui.lbldrawheight->setvisible(false); ui.edtx1->setvisible(true); ui.edty1->setvisible(true); ui.edtw1->setvisible(true); ui.edth1->setvisible(false); void GrafikaQTvel::on_ChkFill_stateChanged(int state) void GrafikaQTvel::on_btnClearDataR_clicked() ui.edtx1->clear(); ui.edty1->clear(); ui.edtw1->clear(); ui.edth1->clear(); ui.btndraw->setenabled(!ui.rbfreedraw->ischecked()); void GrafikaQTvel::_AnyEditChanged() if (ui.rbfreedraw->ischecked())
return; _EnableDrawing(_usedEditCnt); void GrafikaQTvel::on_edtX1_textChanged(QString s) _AnyEditChanged(); void GrafikaQTvel::on_edtY1_textChanged(QString s) _AnyEditChanged(); void GrafikaQTvel::on_edtW1_textChanged(QString s) _AnyEditChanged(); void GrafikaQTvel::on_edtH1_textChanged(QString s) _AnyEditChanged();