Grafika dwuwymiarowa

Podobne dokumenty
Mechanizm sygnałów i slotów. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 4. Sygnały i sloty - definicja klasy

Tłumaczenie i adaptacja materiałów: dr Tomasz Xięski. Na podstawie prezentacji udostępnionych przez Digia Plc. na licencji CC.

Qt - podstawowe cechy

Qt - dialogi. Bogdan Kreczmer. ZPCiR ICT PWR pokój 307 budynek C3

Programowanie w środowiskach RAD QtCreator, Qt i C++

Qt in Education. Sieć I drukowanie

narzędzie Linia. 2. W polu koloru kliknij kolor, którego chcesz użyć. 3. Aby coś narysować, przeciągnij wskaźnikiem w obszarze rysowania.

The Graphics View Framework. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5. he Graphics View Framework - architektura

Programowanie, część III

Wprowadzenie do tworzenia zaawansowanych interfejsów graficznych: QGraphics View Framework vs. QML. Jakub Bogacz. Patryk Górniak

Wizualne systemy programowania. Wykład 11 Grafika. dr Artur Bartoszewski -Wizualne systemy programowania, sem. III- WYKŁAD

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 4

Qt sygnały i designer

Podstawy Swing. Tomasz Borzyszkowski

Obsługa grafiki w Delphi, rysowanie na płótnie, obsługa myszki, zapisywanie obrazków do plików, bitmapy pozaekranowe.

Dynamiczne i wydajne tworzenie interfejsu. Piotr Michałkiewicz

WASM AppInventor Lab 3. Rysowanie i animacja po kanwie PODSTAWY PRACY Z KANWAMI

Architektura interfejsu użytkownika

Edytor tekstu MS Word podstawy

Programowanie w środowiskach RAD Qt i C++

Obsługa mapy przy użyciu narzędzi nawigacji

Grafika i komunikacja człowiek komputer Laboratorium. Część 3: Tekst, czcionki, kolory

Szybkie tworzenie grafiki w GcIde

Rozdział 1. Wstęp 5. Rozdział 2. Pierwsze kroki 13. Rozdział 3. Podstawy rysunku wektorowego 35

Następnie zdefiniujemy utworzony szkic jako blok, wybieramy zatem jak poniżej

Prezentacje multimedialne. MS PowerPoint 2003

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Zaawansowany kurs języka Python

Edytor tekstu OpenOffice Writer Podstawy

CorelDRAW. wprowadzenie

Dodawanie grafiki i obiektów

1.3. Tworzenie obiektów 3D. Rysunek 1.2. Dostępne opcje podręcznego menu dla zaznaczonego obiektu

Inkscape. Menu. 1 SVG (ang. Scalable Vector Graphics) uniwersalny format dwuwymiarowej, statycznej i

Implementacja aplikacji sieciowych z wykorzystaniem środowiska Qt

Kurs WWW. Paweł Rajba.

TEMAT : KLASY DZIEDZICZENIE

PHP 5 język obiektowy

Szablony klas, zastosowanie szablonów w programach

Interfejsy i klasy wewnętrzne

Jak zrobić klasyczny button na stronę www? (tutorial) w programie GIMP

Dodanie nowej formy do projektu polega na:

PyGame Gra w Ponga. Spis treści

Ćwiczenie pochodzi ze strony

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Druga aplikacja Prymitywy, alpha blending, obracanie bitmap oraz mały zestaw przydatnych funkcji wyświetlających własnej roboty.

Jarosław Kuchta Podstawy Programowania Obiektowego. Podstawy grafiki obiektowej

Komputerowe systemy na rynkach finansowych. wykład 5. MQL4 - funkcje operujące na obiektach wykresu

Obsługa programu Paint materiały szkoleniowe

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Wzorce projektowe cz. II. Wzorce projektowe cz. II 1/35

Mechanizm dziedziczenia

Wymiarowanie, kreskowanie, teksty

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Włącza i wyłącza automatyczny hinting. Pozwala na określenie czy chcemy, aby hinting był stosowany również do większych czcionek.

Visual Studio instalacja

Algorytmy i Struktury Danych. Anna Paszyńska

Edytor tekstu OpenOffice Writer Podstawy

Maskowanie i selekcja

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

1. Umieść kursor w miejscu, w którym ma być wprowadzony ozdobny napis. 2. Na karcie Wstawianie w grupie Tekst kliknij przycisk WordArt.

WSTĘP; NARZĘDZIA DO RYSOWANIA

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Narzędzia programu Paint

Programowanie obiektowe

WIZUALIZACJA INFORMACJI TEKSTOWEJ WSTĘP DO HTML 5 CANVAS

Zajęcia nr 15 JavaScript wprowadzenie do JavaScript

Wykład 8: klasy cz. 4

Wprowadzenie do rysowania w 3D. Praca w środowisku 3D

Janusz Ganczarski. OpenGL Pierwszy program

Adobe InDesign lab.1 Jacek Wiślicki, Paweł Kośla. Spis treści: 1 Podstawy pracy z aplikacją Układ strony... 2.

I. Spis treści I. Spis treści... 2 II. Kreator szablonów Tworzenie szablonu Menu... 4 a. Opis ikon Dodanie nowego elementu...

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

POMOC / INSTRUKCJA OBSŁUGI

Ćwiczenie 2 Warstwy i kształty podstawowe

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

Aplikacja po polsku. Bogdan Kreczmer. ZPCiR ICT PWr pokój 307 budynek C3.

Rysowanie punktów na powierzchni graficznej

Podstawy Processingu. Diana Domańska. Uniwersytet Śląski

1. OPEN OFFICE RYSUNKI

Rozdział 3. Zapisywanie stanu aplikacji w ustawieniach lokalnych

EDYCJA TEKSTU MS WORDPAD

Wykład 5 Okna MDI i SDI, dziedziczenie

Zaawansowane programowanie w C++

GRAFIKA WEKTOROWA. WYKŁAD 1 Wprowadzenie do grafiki wektorowej. Jacek Wiślicki Katedra Informatyki Stosowanej

Multimedia i interfejsy. Ćwiczenie 5 HTML5

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Diagram klas UML jest statycznym diagramem, przedstawiającym strukturę aplikacji bądź systemu w paradygmacie programowania obiektowego.

Dziedziczenie. Zadanie 1

Ćw. I Projektowanie opakowań transportowych cz. 1 Ćwiczenia z Corel DRAW

Przygotuj za pomocą tabulatorów element formularza. Utwórz pole tekstowe i sformatuj tak, aby dół napisu w polu był dokładnie nad kropkami.

Builder (budowniczy) Cel: Przykład:

LABORATORIUM 7 Cel: 1_1

Tworzenie szablonów użytkownika

Tworzenie i edycja dokumentów w aplikacji Word.

Qt - edycja, obsługa zdarzeń, rozmieszczenie kontrolek

Wprowadzenie do projektu QualitySpy

Obsługa programu Paint. mgr Katarzyna Paliwoda

Prezentacja multimedialna MS PowerPoint 2010 (podstawy)

Transkrypt:

Grafika dwuwymiarowa

Tłumaczenie i adaptacja materiałów: dr Tomasz Xięski. Na podstawie prezentacji udostępnionych przez Digia Plc. na licencji CC. 2012 Digia Plc. The enclosed Qt Materials are provided under the Creative Commons Attribution-Share Alike 2.5 License Agreement. The full license text is available here: http://creativecommons.org/licenses/by-sa/2.5/legalcode. Digia, Qt and the Digia and Qt logos are the registered trademarks of Digia Plc. in Finland and other countries worldwide.

Z punktu użytkownika: Z punktu programisty: API

Własne widgety mogą ulepszyć bądź zepsuć ogólne wrażenie użytkownika: Własne widgety oferują zazwyczaj dowolne możliwości dostosowania do swoich potrzeb. Własne widgety często wykorzystywane są jako dodatkowa warstwa prezentacji danych np. stworzenie licznika analogowego. Bardziej złożone aplikacje w 99% wykorzystują autorskie widgety. Uwaga użytkownicy przyzwyczajeni są wyłącznie do interakcji ze standardowymi komponentami. Obsługi nowych trzeba ich w pewnych przypadkach uczyć.

Jednym ze sposobów na tworzenie własnych widgetów jest agregacja już istniejących QDial QLabel = ComposedGauge QSlider QVBoxLayout

ComposedGauge::ComposedGauge(QWidget *parent) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); QDial *dial = new QDial(); QLabel *label = new QLabel(); m_slider = new QSlider(); layout->addwidget(dial); layout->addwidget(label); layout->addwidget(m_slider); m_slider->setorientation(qt::horizontal); label->setalignment(qt::aligncenter);...

Wygląd autorskiego komponentu złożonego ze standardowych nie ulega zmianie. Zachowanie zależy od programisty. Przesuń gałkę by zmienić wartość Przesuń suwak by zmienić wartość Ustaw wartość z klawiatury

ComposedGauge::ComposedGauge(QWidget *parent) : QWidget(parent) {... connect(dial, SIGNAL(valueChanged(int)), m_slider, SLOT(setValue(int))); connect(m_slider, SIGNAL(valueChanged(int)), dial, SLOT(setValue(int))); connect(m_slider, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); dial->setfocuspolicy(qt::nofocus); dial->setvalue(m_slider->value()); label->setnum(m_slider->value());... Odpowiednie połączenia zapewniają interakcję miedzy komponentami

Wykorzystanie mechanizmu właściwości i hermetyzacji ułatwia późniejsze udostępnienie i wykorzystanie takich komponentów class ComposedGauge : public QWidget { Q_OBJECT Q_PROPERTY(int value READ value WRITE setvalue) public: explicit ComposedGauge(QWidget *parent = 0); int value() const; public slots: void setvalue(int); signals: void valuechanged(int); private: QSlider *m_slider; };

Obiekt QSlider przechowuje aktualną wartość ComposedGauge::ComposedGauge(QWidget *parent) : QWidget(parent) {... } connect(m_slider, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int))); int ComposedGauge::value() const { return m_slider->value(); } void ComposedGauge::setValue(int v) { m_slider->setvalue(v); }

... ComposedGauge *gauge = new ComposedGauge(); layout->addwidget(gauge); connect(gauge, SIGNAL(valueChanged(int)),... );...

By tworzyć prawdziwie własne komponenty należy: Samemu obsługiwać rysowanie komponentu Obsługiwać zdarzenia: Dotyczące klawiatury Dotyczące myszy Zmiany rozmiaru itp Obsługiwać polityki rozmiarów i zapewnić responsywność komponentów

Rysowanie powinno przebiegać w paintevent. Wyjątek stanowią powierzchnie udostępniane przez Qimage, Qpixmap. Shown Unobstructed The Qt event loop paintevent update called repaint called

Obsługa zdarzeń związanych z rysowaniem sprowadza się do redefinicji funkcji paintevent i użyciu obiektu klasy QPainter class MyWidget : public QWidget {... protected: void paintevent(qpaintevent*); void MyWidget::paintEvent(QPaintEvent *ev) { QPainter p(this);...

Obiekty QPainter mogą rysować na obiektach typu QPaintDevice tj.: QWidget QImage niezależne sprzętowo QPixmap do pokazywania na ekranie QPrinter QPicture zapisuje oraz replikuje komendy rysowania QSvgGenerator zapisuje komendy rysowania i tworzy na ich podstawie plik SVG

Obiekt QPainter służy do rysowania figur Obrysy są rysowane przez QPen QPainter p(... ); QPen pen(qt::black, 5); p.setpen(pen); p.drawpolygon(polygon); Wnętrze jest wypełniane przez QBrush QPainter p(... ); p.setpen(qt::nopen); p.setbrush(qt::red); p.drawpolygon(polygon);

Prosta implementacja metody paintevent Standardowe pióro jest czarne void RectWithCircle::paintEvent(QPaintEvent *ev) { QPainter p(this); } p.setbrush(qt::green); p.drawrect(10, 10, width()-20, height()-20); p.setbrush(qt::yellow); p.drawellipse(20, 20, width()-40, height()-40);

QColor - używany do reprezentacji kolorów QColor c = QColor(red, green, blue, alpha=255); Argumenty red, green, blue i alpha przyjmują wartości z zakresu od 0 do 255 Kanał alpha kontroluje przeźroczystość 255 pełne wypełnienie kolorem 0 kolor jest przeźroczysty

Wartości na osi X rosną na prawo Wartości na osi Y rosną w dół Współrzędne mogą być: globalne lokalne (do widżetu) x y

Qt wykorzystuje klasy do reprezentowania figur i rozmiarów: QPoint punkt (x, y) QSize rozmiar (width, height) QRect punkt i rozmiar (x, y, width, height) Przydatne funkcje to: topleft, topright, bottomleft, bottomright i size QPointF/QSizeF/QRectF do reprezentowania współrzędnych rzeczywistych.

Większość funkcji do rysowania pozwala na podanie współrzędnych na wiele dogodnych sposobów: drawrect(qrectf r); drawrect(qrect r); drawrect(int x, int y, int w, int h); drawpoint(qpointf p); drawpoint(qpoint p); drawpoint(int x, int y);

QPainter::drawPoint QPainter::drawLine QPainter::drawRect QPainter::drawRoundedRect

QPainter::drawEllipse QPainter::drawArc QPainter::drawPie Kąty podawane są jako wielokrotność 16 stopni. 4320 2880 0 / 5760 1440

QPainter::drawText QPainter p(this); QFont font("helvetica"); p.setfont(font); p.drawtext(20, 20, 120, 20, 0, "Hello World!"); font.setpixelsize(10); p.setfont(font); p.drawtext(20, 40, 120, 20, 0, "Hello World!"); font.setpixelsize(20); p.setfont(font); p.drawtext(20, 60, 120, 20, 0, "Hello World!"); QRect r; p.setpen(qt::red); p.drawtext(20, 80, 120, 20, 0, "Hello World!", &r); Prostokąt r określa maksymalne granice tekstu

QPainter::scale QPainter::translate QPainter::rotate QPainter::shear

Kolejność transformacji jest istotna Punkt początkowy jest również istotny p.translate(0, 100); p.rotate(35); p.drawrect(-60, -60, 120, 120); p.rotate(35); p.translate(0, 100); p.drawrect(-60, -60, 120, 120);

Metody save i restore, pozwalają trzymać stan transformacji na stosie Przykład: obrót według punktu QPoint rotcenter(50, 50); qreal angle = 42; p.save(); p.translate(rotcenter); p.rotate(angle); p.translate(-rotcenter); p.setbrush(qt::red); p.setpen(qt::black); p.drawrect(25,25, 50, 50); Wykonaj transformacje Czerwony prostokąt p.restore(); p.setpen(qt::nopen); p.setbrush(qcolor(80, 80, 80, 150)); p.drawrect(25,25, 50, 50); Szary prostokąt

Obrót jest możliwy względem dowolnej osi, co pozwala na uzyskanie efektu 3D QTransform t; t.rotate(60, Qt::YAxis); painter.settransform(t, true);

Przykład własnego komponentu: CircularGauge Działa jak CombinedGauge, ale to w pełni własny komponent API posiada takie samo jak CombinedGauge Rysowanie jest autorskie Może reagować na: klawiaturę mysz

Tworzenie tła wskaźnika void CircularGauge::paintEvent(QPaintEvent *ev) { QPainter p(this); int extent; if (width()>height()) extent = height()-20; else extent = width()-20; Wyśrodkowanie wskaźnika p.translate((width()-extent)/2, (height()-extent)/2); p.setpen(qt::white); p.setbrush(qt::black); p.drawellipse(0, 0, extent, extent); Rysowanie czarnego koła...

Rysowanie skali void CircularGauge::paintEvent(QPaintEvent *ev) {... p.translate(extent/2, extent/2); for(int angle=0; angle<=270; angle+=45) { p.save(); p.rotate(angle+135); p.drawline(extent*0.4, 0, extent*0.48, 0); p.restore(); }... Proszę zwrócić uwagę na wykorzystanie funkcji save i restore wewnątrz pętli.

Rysowanie strzałki void CircularGauge::paintEvent(QPaintEvent *ev) {... p.rotate(m_value+135); QPolygon polygon; polygon << QPoint(-extent*0.05, extent*0.05) << QPoint(-extent*0.05, -extent*0.05) << QPoint(extent*0.46, 0); p.setpen(qt::nopen); p.setbrush(qcolor(255,0,0,120)); p.drawpolygon(polygon); } Strzałka bez transformacji to zwykły wielokąt

Potencjalnie własny komponent może reagować na wiele różnych zdarzeń związanych z: Obsługą klawiatury Obsługą myszy Obsługą okna, dotyku, gestów, zdarzeń czasowych, zmian stanu, schowka, przeciągania itp.

Należy przeciążyć keypressevent Dopisać kod obsługi interesujących klawiszy Nieużywane klawisze należy przekazać do obsługi w klasie bazowej void CircularGauge::keyPressEvent(QKeyEvent *ev) { switch(ev->key()) { case Qt::Key_Up: case Qt::Key_Right: setvalue(value()+1); break; case Qt::Key_Down: case Qt::Key_Left: setvalue(value()-1); break; case Qt::Key_PageUp: setvalue(value()+10); break; case Qt::Key_PageDown: setvalue(value()-10); break; default: QWidget::keyPressEvent(ev); } }

Zdarzenia związane z obsługą myszy obsługiwane są poprzez przeciążenie następujących metod: mousepressevent i mousereleaseevent mousemoveevent wywoływane tylko jeśli przycisk jest wciśnięty, chyba że właściwość mousetracking jest ustawiona setvaluefrompos to prywatna metoda do konwersji współrzędnych w kąt void CircularGauge::mousePressEvent(QMouseEvent *ev) { setvaluefrompos(ev->pos()); } void CircularGauge::mouseReleaseEvent(QMouseEvent *ev) { setvaluefrompos(ev->pos()); } void CircularGauge::mouseMoveEvent(QMouseEvent *ev) { setvaluefrompos(ev->pos()); }

Metoda paintevent przyjmuje QPaintEvent jako argument Klasa QPaintEvent ma m.in. dwie metody: QRect rect zwraca prostokąt, który musi zostać przerysowany QRegion region zwraca region, który musi zostać przerysowany Region jest bardziej skomplikowaną strukturą od prostokąta Podczas przerysowywania, unikaj rysowania skomplikowanych figur poza wyznaczonym regionem/prostokątem

QTimer generuje zdarzenia czasowe MyClass(QObject *parent) : QObject(parent) { QTimer *timer = new QTimer(this); timer->setinterval(5000); connect(timer, SIGNAL(timeout()), this, SLOT(doSomething()); timer->start(); } Co 5000ms tj. co 5s Może też służyć opóźnieniu akcji QTimer::singleShot(1500, dest, SLOT(doSomething());

Wszystkie zdarzenia osadzane są na tzw. kolejce zdarzeń Implikuje to specyficzne przetwarzanie zdarzeń Tylko ostatnie zdarzenie mousemoveevent będzie dostarczone do kolejki Wiele zdarzeń typu paintevent może zostać złączonych Gdy QObject otrzymuje zdarzenie, metoda event zostaje wywołana Metoda event może zaakceptować (accept) bądź odrzucić (ignore) dane zdarzenie Odrzucone zdarzenia są dalej przetwarzane zgodnie z hierarchią obiektów

Istnieje możliwość założenia filtrów na dowolnym obiekcie typu QObject Filtr sam w sobie jest specyficznym obiektem QObject, który implementuje metodę eventfilter Filtr otrzymuje zdarzenia kierowane do obserwowanego obiektu i może je zatrzymać bądź przekazać dalej Może być przydatny by dodać funkcję do danego obiektu bez konieczności tworzenia podklasy Może służyć jako blokada dla określonych zdarzeń

Implementacja filtra dla wskaźnika Dodanie funkcji: Naciśnięcie zera powoduje wyzerowanie wartości wskaźnika class KeyboardFilter : public QObject... bool KeyboardFilter::eventFilter(QObject *o, QEvent *ev) { if (ev->type() == QEvent::KeyPress) if (QKeyEvent *ke = static_cast<qkeyevent*>(ev)) if (ke->key() == Qt::Key_0) if (o->metaobject()->indexofproperty("value")!= -1 ) { o->setproperty("value", 0); return true; } } return false; true nie przekazuj zdarzenia do obserwowanego obiektu

Aktywacja filtra sprowadza się do wywołania metody installeventfilter ComposedGauge compg; CircularGauge circg; KeyboardFilter filter; compg.installeventfilter(&filter); circg.installeventfilter(&filter); Ponieważ filtry związane są z konkretną właściwością a nie klasą, mogą być używane z obiektami typu QSlider, QDial, QSpinBox, itp. Możliwe jest instalowanie filtra nawet na QApplication

Qt rysuje komponenty używając różnych styli na konkretnej platformie Style mogą być kontrolowane z linii poleceń:./myapplication -style name-of-style By dany widżet dobrze integrował się z daną platformą, musi on reagować na zmiany stylu: Korzystaj ze standardowych komponentów Używaj elementów specyficznych dla danej platformy podczas rysowania Bierz pod uwagę rozmiary zdefiniowane w danym stylu

Dostosowanie komponentu do wielu różnych platform nie jest zadaniem trywialnym Rozważ wykorzystanie istniejących komponentów Bezpośrednio lub jako złożenie Użyj komponentu typu QFrame jako bazy jeżeli komponent ma być niezależny od stylu platformy

Złożone komponenty tworzone są z mniejszych Wykorzystują proste elementy Style wpływają na elementy kontrolne Pamiętaj o miarach Wykorzystuj pixmapy

Rysując z wykorzystaniem obiektów Qstyle, wykorzystywana jest pomocnicza instancja QStyleOption, która niesie ze sobą informacje : Czcionce Palecie kolorów Położeniu na ekranie (w formie prostokąta) Stanie (aktywny, wybrany itp) Specyficznych ustawień danego elementu (jak jego ikona czy tekst)

void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); QStyleOptionFocusRect option; option.initfrom(this); option.backgroundcolor = palette().color(qpalette::background); } style()->drawprimitive(qstyle::pe_framefocusrect, &option, &painter, this);

Klasa QStylePainter agreguje klasy QPainter oraz QStyle void MyWidget::paintEvent(QPaintEvent *event) { QStylePainter painter(this); QStyleOptionFocusRect option; option.initfrom(this); option.backgroundcolor = palette().color(qpalette::background); } painter.drawprimitive(qstyle::pe_framefocusrect, option);

Własne widżety można wykorzystać bezpośrednio z poziomu modułu QtDesigner. Stwórz wtyczkę implementującą interfejs QDesignerCustomWidgetInterface Więcej informacji znajdziesz w http://doc.qt.io/qt-5/designer-creating-customwidgets.html

Prócz klasy QPainter istotne jest zapoznanie się z podstawowymi klasami pomocniczymi: QColor do reprezentacji koloru QPen do rysowania obwodów QBrush do wypełniania wnętrza

Konstruktor klasy QColor przyjmuje 3 argument oznaczające składowe koloru oraz jeden określający poziom przeźroczystości QColor( int r, int g, int b, int a ) Qt dostarcza szeregu predefiniowanych kolorów:

Przestrzeń barw RGB jest jednym z najpopularniejszych używanych modeli, ale istnieją również inne: CMYK wykorzystywany w druku HSV / HSL wykorzystywany w dialogach wyboru kolorów QColor może zostać określony z wykorzystaniem dowolnej przestrzeni barw poprzez wykorzystanie jednej z metod: QColor::fromCmyk QColor::fromHsl QColor::fromHsv

Wartości poszczególnych składowych modeli RGB, CMYK, HSL i HSV mogą być odczytane przez getrgb, getcmyk, gethsl, gethsv Mogą być również pobierane indywidualnie wykorzystując metody: red, green, blue, cyan and magenta, yellow, black hslhue, hslsaturation, lightness hsvhue, hsvsaturation, value alpha getrgb(int *r, int *g, int *b)

Klasa QColor umożliwia również tworzenie ciemniejszych bądź jaśniejszych kolorów QColor::lighter( int factor ) QColor::darker( int factor ) darker Qt::red lighter

Klasa QColor służy do reprezentacji kolorów, ale do ich przechowywania rekomendowane jest prostsze rozwiązanie. Klasa QRgb nada się w tym celu zdecydowanie lepiej

Konstruktor: QRgb orange = qrgb(255, 127, 0); QRgb overlay = qrgb(255, 0, 0, 100); Wartości poszczególnych składowych odczytasz przez qred, qgreen, qblue, qalpha int red = qred(orange); Możliwa jest również konwersja do skali szarości z wykorzystaniem funkcji qgray int gray = qgray(orange);

Podczas rysowania obrysu danego komponentu, klasa QPen jest uzywana Każde pióro posiada właściwości takie jak kolor, szerokość czy styl linii Pióra mogą w tzw. trybie cosmetic co oznacza, że nie wpływają na nie żadne transformacje Ustaw używając setcosmetic(bool) Może pozytywnie wpłynąć na ogólną wydajność aplikacji

Styl linii ustawiany jest przez metodę setstyle Qt::SolidLine Qt::DashLine Qt::DotLine Qt::DashDotLine Qt::DashDotDotLine Qt::CustomDashLine kontrolowane przez dashpattern

joinstyle Qt::BevelJoin (domyślne) capstyle Qt::SquareCap (domyślne) Qt::MiterJoin Qt::FlatCap Square pokrywa punkt końcowy, flat nie Qt::RoundJoin Qt::RoundCap

Pędzle wykorzystywane są do wypełnienia wnętrza kształtu Występuje szereg rodzajów pędzli, dostępnych za pośrednictwem klasy QBrush Mogą być podzielone na następujące grupy Pełne Wzorcowe Teksturowe Gradientowe

Pędzle tego typu, pokrywające dokładnie zadany kształt tworzone są z wykorzystaniem konstruktrów: QBrush red(qt::red); QBrush odd(qcolor(55, 128, 97));

Zwykły pędzel jest tak naprawdę szczególnym przykładem pędzla z nadanym wzorcem. QBrush( const QColor &color, Qt::BrushStyle style )

Tekstura definiowana jest jako obiekt typu QPixmap QBrush( const QPixmap &pixmap ) QPixmap pacpixmap("pacman.png"); painter.setpen(qpen(qt::black, 3)); painter.setbrush(pacpixmap); painter.drawellipse(rect()); Jeżeli tekstura jest monochromatyczna, używany jest kolor pędzla. W przeciwnym razie brany pod uwagę jest kolor pixmapy.

QLinearGradient QRadialGradient QConicalGradient Stwórz pędzel poprzez podanie argumentu typu Qgradient: QBrush b = QBrush( QRadialGradient(... ) );

Gradienty rozkładają kolor w zakresie od 0.0 do 1.0 QGradient::setColorAt( qreal pos, QColor ); Możliwe jest jednak osiągnięcie bardziej zaawansowanego efektu: PadSpread (default) RepeatSpread ReflectSpread

setcolorat(0.7, QColor(255, 0, 0)) setcolorat(0.0, QColor(0, 0, 0)) setcolorat(1.0, QColor(255, 255, 0))

Każdy pędzel powiązany jest z obiektem QPainter. By to powiązanie usunąć: QPainter p; p.setpen(qt::nopen); p.setbrush(qt::nobrush); Zmiana pióra bądź pędzla może być operacją kosztowną Należy nadmiernych zmian unikać i dobrze zaplanować rysowanie

Rysowanie tekstu może być skomplikowanym zadaniem. Należy wziąć pod uwagę: Rozmiar czcionki Wyrównanie Odstępy Zawijanie tekstu Zawijanie wokół obrazków Sposób pisania: od lewej do prawej czy odwrotnie

Podstawowe rysowanie tekstu: drawtext( QPoint, QString ) Dodatkowe opcje: drawtext( QRect, QString, QTextOptions ) Określenie zajętego obszaru: drawtext( QRect, flags, QString, QRect* )

Klasa QFont reprezentuje podstawowe właściwości związane z daną czcionką takie jak: Krój czcionki Rozmiar Pogrubienie / Kursywę / Podkreślenie / Przekreślenie itp.

Stwórz nową instancję klasy QFont podając nazwę czcionki: QFont font("helvetica"); font.setfamily("times"); Użyj QFontDatabase::families by dostać listę dostępnych czcionek: QFontDatabase database; QStringList families = database.families();

Rozmiar czcionki może być podawany w pikselach bądź punktach QFont font("helvetica"); font.setpointsize(14); // 12 points high // depending on the paint device's dpi font.setpixelsize(10); // 10 pixels high Można zauważyć, że pixelsize == -1 jeżeli rozmiar został ustawiony z wykorzystaniem metody setpointsize i odwrotnie

Czcionka może mieć narzucony styl: Normal, bold, italic, strike out, underline, overline QWidget::font i QPainter::font zwracają stałą referencję (const QFont), dlatego modyfikuje się jej kopię: QFont tempfont = w->font(); tempfont.setbold( true ); w->setfont( tempfont );

Często potrzebna jest wiedza na temat rozmiaru tekstu zanim zostanie on narysowany QFontMetrics jest wykorzystywana do pomiarów Funckja boundingrect ułatwia pomiar rozmiaru bloku tekstu QImage image(200, 200, QImage::Format_ARGB32); QPainter painter(&image); QFontMetrics fm(painter.font(), &image); qdebug("width: %d", fm.width("hello Qt!")); qdebug("height: %d", fm.boundingrect(0, 0, 200, 0, Qt::AlignLeft Qt::TextWordWrap, loremipsum).height());

Wyrównanie tekstu nie należy do spraw najprostszych

Klasa QTextDocument jest używana do tworzenia dokumentów z uwzględnieniem ich formatowania: Składają się z bloków tekstu - QTextBlock Wykorzystują silnik renderowania tekstu QAbstractTextDocumentLayout Możliwe jest narysowanie sformatowanego dokumentu na dowolny obiekt typu QPainter

QTextDocument QTextBlock QAbstractTextDocumentLayout Do zmiany pozycji i modyfikacji dokumentów QTextLayout Zmiana układu następuje po zmianie treści QTextCursor

Użyj metody drawcontents by narysować zawartość dokumentu: QPainter painter; QTextDocument doc; doc.settextwidth(width()); doc.drawcontents(&p, rect()); Użyj settextwidth by ograniczyć szerokość tekstu

QPixmap Dobra do pokazywania rysunków na ekranie QImage Dobra do manipulowania rysunkami Nawet przy dwukrotnym rysowaniu obiektu typu QImage na ekran, korzystniej jest najpierw przekonwertować go na typ QPixmap

Konwersja między typami QImage oraz QPixmap sprowadza się do wykorzystania statycznych metod: QImage QPixmap::toImage(); QPixmap QPixmap::fromImage( const QImage& );

QPixmap pixmap( "image.png" ); pixmap.save( "image.jpeg" ); QImage image( "image.png" ); image.save( "image.jpeg" ); Powyższy kod wykorzystuje niejawnie klasy QImageReader i QImageWriter. Określają one format rysunku przy zapisie na podstawie rozszerzenia pliku

Klasa QImage dziedziczy po QPaintDevice, więc obiekt QPainter może rysować na niej bezpośrednio: QImage image( 100, 100, QImage::Format_ARGB32 ); QPainter painter(&image); painter.setbrush(qt::red); painter.fillrect( image.rect(), Qt::white ); painter.drawrect( image.rect().adjusted( 20, 20, -20, -20 ) );

QPixmap jest zoptymalizowana do pokazywania zawartości na ekranie void MyWidget::imageChanged( const QImage &image ) { pixmap = QPixmap::fromImage( image ); update(); } void MyWidget::paintEvent( QPaintEvent* ) { QPainter painter( this ); painter.drawpixmap( 10, 20, pixmap ); }

Format SVG jest standardem W3C do opisu grafiki wektorowej poprzez wykorzystanie języka XML Qt wspiera zarówno generowanie jak i odczyt plików SVG Wszystkie klasy powiązane z SVG dostępne są w module QtSvg

Za odczyt danych typu SVG odpowiada obiekt klasy QSvgRenderer: QPainter painter; QSvgRenderer renderer; renderer.load(qstring("svg-test.svg")); renderer.render(&painter); Metody defaultsize oraz viewbox określają rozmiar grafiki

Przy generowaniu grafiki SVG pomocna jest klasa QSvgGenerator: QSvgGenerator generator; generator.setfilename("svg-test.svg"); generator.setsize(qsize(200, 200)); generator.setviewbox(qrect(0, 0, 200, 200)); QPainter p; p.begin(&generator); p.setpen(qt::black); p.setbrush(qt::yellow); p.drawpie(0, 0, 200, 200, 22*16, 316*16); p.drawellipse(125, 35, 5, 5); p.end();