Kurs Qt – Część 6 – Rysowanie

Matthew @ 2010-02-24 — Kategorie: Kurs Qt, Programowanie, Qt, Techblog

6. (z dużym opóźnieniem) część kursu Qt. Z racji, że ostatnio zostałem zmuszony do rysowania grafów itp. rzeczy (na szczęście można było wybrać technologię) to dziś przedstawię właśnie rysowanie (proste, nie grafów, za dużo nerwów mnie to kosztowało ;P) w Qt. Przy okazji mały pokaz jak zrobić menu kontekstowe

Myślę, że pliku main.cpp nie muszę już przedstawiać, więc od razu przejdę do tego co należy wsadzić do nagłówka i dlaczego:

Na początku zdefiniowaliśmy sobie enuma, dzięki któremu będziemy mogli w łatwy sposób definiować co będziemy rysować narysować. Dalej mamy zwykłą klasę dziedziczącą po QWidget. Dalej, deklarujemy przesłonięcie metod odpowiedzialnych za obsługę zdarzeń związanych kolejno z: rysowaniem, naciśnięciem myszy, przesunięciem myszy oraz menu kontekstowym. Dalej są sloty, których zadaniem będzie ustawianie co chcemy rysować. Trochę zmiennych pomocniczych. Zmienna narysuj powie nam czy w danej chwili chcemy rysować, dynamicznie czy będzie możliwa zmiana rozmiaru rysowanego obiektu, x i y opisują współrzędne początkowe obiektu a dx i dy różnicę od kliknięcia do przesunięcia w przypadku zmiany rozmiaru. Dalej są akcje które dodamy do menu abyśmy mogli wywoływać zmiany tego co i jak chcemy rysować.

Natomiast definicja metod klasy wygląda tak:

Pierwszą metodą jest konstruktor klasy Widget. Wszystko co zostało tam użyte powinno być już wam znane z poprzednich części kursu. Jedyna nowość to ustawienie akcji możliwości bycia zaznaczaną (linia 22). Dalej mamy domyślny destruktor, żeby przejść do metody paintEvent(). W niej umieścimy kod odpowiedzialny za rysowanie. Najważniejszym komponentem tej metody jest obiekt klasy QPainter (linia 34.), to przy pomocy jego metod będziemy rysowali. A żeby nie było całkiem nudno ustawimy jakiś wesoły kolor. W tym celu tworzymy zmienną klasy QColor, która będzie przechowywała nasz wybrany kolor (linia 36.). Ustawiamy wybrany kolor naszemu obiektowi QPainter poprzez metodę setPen() (linia 38.), z nią, jak również z innymi metodami ustawiającymi różne właściwości QPaintera, polecam się zapoznać poprzez przejrzenie dokumentacji. W liniach 43, 47 oraz 51 mamy wywołania metod rysujących odpowiednio koło, kwadrat oraz napis na widgetcie. Metodom tym podajemy x i y miejsca od którego ma się zacząć rysowanie (lewy górny róg figury) oraz szerokość i wysokość jaką figura ma mieć. W przypadku napisu, zamiast szerokości i wysokości podajemy sam napis. Po resztę metod również odsyłam do dokumentacji. Metoda paintEvent() jest wywoływana przy każdym przerysowaniu (repaint()) lub aktualizacji stanu widgeta (update()).
Dalej mamy metody mousePressEvent() oraz mouseMoveEvent(). Są wywoływane odpowiednio, przy wciśnięciu myszy oraz przy jej ruchu. Pierwszej używamy do narysowania obiektu (w zasadzie to pobrania współrzędnych i powiedzenie metodzie paintEvent(), że chcemy coś narysować), a drugiej do zmiany rozmiarów tych obiektów. Aby możliwe było rysowanie tylko lewym przyciskiem myszy, sprawdzamy który został wciśnięty, poprzez wywołanie metody button() z obiektu klasy QMouseEvent i porównujemy go z enumem reprezentującym odpowiedni przycisk (linia 64.)
Metoda contextMenuEvent, służy do wyświetlania menu kontekstowego. Różnica między takim tworzeniem menu, w stosunku do poprzednich części kursu, jest taka, że za każdym wywołaniem tej metody tworzymy nowy obiekt QMenu, oraz musimy go ręcznie wywołać metodą exec() (linia 95.) podając jako parametr współrzędne w którym ma się pojawić menu.

Myślę, że pozostała część kodu nie wymaga wyjaśnienia, a jeżeli ktoś jej nie rozumie to będzie to dobre ćwiczenie dla niego. ;) Jeżeli jednak ktoś całkiem przy tym polegnie, to proszę śmiało pisać w komentarzach. Temat rysowania zostanie, jak znajdę chwilę czasu, poszerzony o transformacje narysowanych obiektów.

EDIT:

Ponieważ bigfun trochę marudził, że mu się nie chce kodu przeklepywać, a z chęcią by przetestował błędy jakie zrobiłem w kodzie więc od dzisiaj każda następna (a może i znajdę czas na poprzednie) porcja kodu będzie opakowywana w repozytorium gita: git://github.com/matthewpl/qt6.git.

Komentarze:

Nie mogę poradzić sobie ze śćiągnięciem całości kodu z git://github.com/pingwinek/qt6.git. Da się wrzucic na jakiś serwer?

@maciek: ja sobie poradziłem bez problemu, więc nie widzę sensu wrzucania tego gdzieś indziej. I co znaczy „nie mogę poradzić sobie”? Może po prostu używasz nie tego co trzeba (w sensie próbujesz po http, zamiast gitem)?

Kurs po prostu świetny. Miałem kurs Qt na studiach, ale dopiero teraz zrozumiałem to Qt:D

Przepisałem kody co do joty i niestety u mnie ( Kubuntu 13.04 ) program nie działa.
Skasowałem treść swoich plików i na wszelki wypadek skopiowałem ze strony, metodą ctrl+c, ctrl+v.
Nie wiem dlaczego tak jest. Programy z poprzednich rozdziałów, po drobnych poprawkach działały bez zarzutu. W tym przykładzie wyskakuje puste okienko – i nic. Żadne klikanie, przeciąganie, wciskanie klawisza MENU na klawiaturze nie powoduje żadnej akcji.
Wiem, że to nie jest forum, ale jeśli macie jakieś pomysły, to byłbym wdzięczny za odpowiedź – przyda się innym.
A co do samego kursu, to bardzo fajny dla kogoś, kto ewentualnie chciałby się zainteresować QT. Opisy mogłyby być nieco obszerniejsze, ale generalnie jest OK. :).

Bardzo dobry kurs QT. Niestety mam problem. Przepisałem kod i przy próbie kompilacji dostaję 66 komunikatów tego typu „undefined reference to ‚_imp__ZN7QActionC1ERK7QStringP7QObject'”. Szukałem rozwiązania za pomocą google, ale bezskutecznie. Używam QT Creatora 2.8.1 i Qt5.1.1 oraz Widows 8.

na Qt5 przeba dodać niestety includy: QWidget QAction QPaintEvent QMouseEvent QMenu

U mnie na Qt5.2 działa. Trzeba tylko zrobić to o czym pisał jamek w pliku widget.h, Poza tym plik main powinien odpowiednio wyglądać. Należy stworzyć obiekt typu Widget. U mnie cały main wygląda tak:
#include
#include

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget r;
r.show();
return a.exec();
}

a tak pro:

QT += widgets
QT += core

QT += gui

TARGET = rysowanie
CONFIG += console
CONFIG += app_bundle

TEMPLATE = app

SOURCES += main.cpp \n widget.cpp

HEADERS += \n widget.h

Dodaj komentarz:

 

Subscribe without commenting