Search
Cílem cvičení je ukázat, jak je možné v QT kreslit grafická primitiva. Využijeme k tomu zejména třídu QPainter, která umožňuje kreslení do jednotlivých GUI komponent.
Při práci s třídou QPainter využijeme skutečnosti, že při vykreslování komponent a takových změnách v aplikaci za běhu, které mohou ovlivňovat grafickou podobu (např. změna velikosti okna), je automaticky volána metoda paintEvent, kterou lze v derivované třídě přepsat 1). Kromě implicitního volání lze metodu paintEvent explicitně volat pomocí metod repaint a update.
class Canvas : public QWidget { Q_OBJECT public: Canvas (QWidget *parent=0); void paintEvent (QPaintEvent *event); };
Canvas::Canvas (QWidget *parent) : QWidget (parent) { resize(200, 200); }
Aby mohl painter kreslit, musí vědět kam: k tomu slouží parametr konstruktor, tzv. painting device - může to být instance třídy QWidget, QPixmap nebo QImage. Zde pracujeme s třídou derivovanou z QWidget, předáme tedy ukazatel this. POkud by bylo potřeba mít z libovolného důvodu painter sdílený v rámci třídy, je třeba ho před začátkem vykreslování aktivovat metodou QPainter::begin() a ukončit metodou QPainter::end().
painting device
this
void Canvas::paintEvent(QPaintEvent *event) { QPainter p(this); p.fillRect(20, 20, 160, 160, QColor(220,0,0)); }
Třída QPainter obsahuje řadu funkcí, pomocí který se do kreslit do painting device. Některé z nich vyžadují, aby bylo zvoleno pero, tj. vytvořena instance třídy QPen.
QPen pen(Qt::black, 2); p.setPen(pen); p.drawRect(40, 40, 30, 30);
Barvy lze používat buď předdefinované (statické atributy třídy QColor), nebo lze definovat libovolnou barvu pomocí souřadnic v některém z barevných modelů (např. defaultním RGB modelu). Součástí specifikace barvy může být i průhlednost, definovaná jako parametr instance QColor nebo pomocí metody QColor::setOpacity().
RGB
for (int i=0; i < 10; i++) { p.setOpacity((i+1)*0.1); p.fillRect(i*40, 0, 40, 40, Qt::darkGray); }
Barevný prostor RGB, který je mainstreamem ve zpracování barevné informace, má celou řadu nevýhod. Díky tomu, že intenzita jednotlivých komponent modelu barvy ovlivňuje jas i barevnost, není možné např. jednoduše provádět porovnávání barev ve smyslu světlejší, tmavší a podobně. Výhodnější proto někdy mohou být barevné modely, ve kterých je jasová složka oddělena od barevné informace, např. barevný prostor HSV - Hue je barva (0-359), Saturation je sytost (0-255) a Value je jas (0-255).
světlejší
tmavší
HSV
Hue
Saturation
Value
for (int i=0; i < 10; i++) { QColor c; p.fillRect(i*40, 0, 40, 40, c.fromHsv(200, i*25, 255)); }
Pomocí třídy QPainter je možné i vytvářet texty. V následujícím příkladu je ukázáno, jak napsat text pomocí metody QPainter::drawText() a nastavit font instancí třídy QFont. Příklad je zajímavý tím, že ukazuje možnost rotace a posunu kreslící plochy (painteru) pomocí metod QPainter::rotate() a QPainter::translate(). Třešničkou je použití lineárního gradientu QLinearGradient při vykreslení písma.
QPainter q(this); QLinearGradient gradient (0, 20, 200, 20); gradient.setColorAt(1.0, Qt::red); gradient.setColorAt(0.0, Qt::yellow); q.setPen(QPen(gradient, 4)); q.setFont(QFont("Arial", 24, QFont::Bold)); q.rotate(90); q.translate(200, -200); for (int i = 0; i < 4; i++) { q.drawText(10, 10, tr("Ahoj PPC")); q.rotate(90); }
Změna kreslící plochy (rotace, translace, transformace) je jednou dalších možností, jak kreslit pomocí https://doc.qt.io/qt-5/qpainter.html. Pro vytváření transformovaných objektů je vhodné vytvářet další instance této třídy, nebo uložit stav pomocí QPainter::save() do zásobníku, odkud může být vyzvednut po provedení transformace metodou QPainter::restore().