Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałJózef Barcicki Został zmieniony 11 lat temu
1
Rozdział 5 Creating custom widgets Autor: Bartłomiej Suliga
2
Przekształcanie istniejących widgetów HexSpinBox- spin box z wartościami w notacji szesnastkowej Dziedziczymy po klasie QSpinBox Implementujemy niektóre metody
3
HexSpinBox.h #ifndef HEXSPINBOX_H #define HEXSPINBOX_H #include class QRegExpValidator; class HexSpinBox : public QSpinBox { Q_OBJECT //makro wymagane dla klas, w których definiowane są sloty sygnały lub właściwości. public: HexSpinBox(QWidget *parent = 0); //konstruktor protected: // trzy funkcje z QSpinBox, które musimy zaimplementwać QValidator::State validate(QString &text, int &pos) const; int valueFromText(const QString &text) const; QString textFromValue(int value) const; private: QRegExpValidator *validator; }; #endif
4
HexSpinBox.cpp #include //plik z definicjami wszystkich klas QtGui #include "hexspinbox.h //nasz plik nagłówkowy HexSpinBox::HexSpinBox(QWidget *parent) : QSpinBox(parent) { setRange(0, 255); //ustawiamy domyślny zakres od 0x00 do 0xFF validator = new QRegExpValidator(QRegExp("[0-9A-Fa-f]{1,8}"), this); //akceptujemy wyrażenia o długości od 1-8 znaków z zakresu 0-9, a-f,A-F } QValidator::State HexSpinBox::validate(QString &text, int &pos) const { return validator->validate(text, pos); } //funkcja sprawdza czy wprowadzony tekst jest poprawny, może zwrócić trzy różne wyniki: Invalid (tekst niepoprawny), Intermediate ( część tekstu nadaje się do przyjęcia) lub Acceptable (tekst poprawny).
5
HexSpinBox.cpp QString HexSpinBox::textFromValue(int value) const { return QString::number(value, 16).toUpper(); } //funkcja zamienia wartość całkowitą na string, używana kiedy zmieniamy wartość za pomocą strzałek SpinBoxa. Używa statycznej funkcji number z drugim argumentem 16, żeby przekonwertować wartość na szestanstkową int HexSpinBox::valueFromText(const QString &text) const {bool ok; return text.toInt(&ok, 16); } // konwersja odwrotna używana kiedy wpisujemy wartość ręcznie i wciśniemy enter, gdy wprowadzona wartość nie jest poprawnym wyrażeniem szesnastkowym parametr ok. przyjmie wartość false;
6
Tworzenie własnego widgetu. Icon Editor- prosty widget do edycji ikon Dziedziczymy po klasie QWidget Implementujemy niektóre metody i zdarzenia
7
IconEditor.h #ifndef ICONEDITOR_H #define ICONEDITOR_H #include class IconEditor : public QWidget { Q_OBJECT //makra do ustawiania niektórych właściwości(każde posiada swój typ oraz funkcje READ i WRITE) Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor) Q_PROPERTY(QImage iconImage READ iconImage WRITE setIconImage) Q_PROPERTY(int zoomFactor READ zoomFactor WRITE setZoomFactor) public: IconEditor(QWidget *parent = 0); void setPenColor(const QColor &newColor); QColor penColor() const { return curColor; } void setZoomFactor(int newZoom);
8
IconEditor.h int zoomFactor() const { return zoom; } void setIconImage(const QImage &newImage); QImage iconImage() const { return image; } QSize sizeHint() const; protected: //zdarzenia klasy QWidget, które musimy implementować void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); private: void setImagePixel(const QPoint &pos, bool opaque); QRect pixelRect(int i, int j) const; //prywatne pola przechowujące właściwości QColor curColor; QImage image; int zoom; }; #endif
9
IconEditor.cpp #include #include "iconeditor.h" IconEditor::IconEditor(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_StaticContents); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); //widget może być rozszerzony, jednak nie może być zmniejszony poniżej minimum curColor = Qt::black; //ustawiamy kolor na czarny zoom = 8; // każdy pixel ikony w edytorze będzie przedstawony jako kwadrat 8x8 image = QImage(16, 16, QImage::Format_ARGB32); //Bitmapa 16 x 16 pixeli w formacie ARGB image.fill(qRgba(0, 0, 0, 0));//wypełniamy bitmapę } QSize IconEditor::sizeHint() const //funkcja zwraca idealny rozmiar widgetu { QSize size = zoom * image.size(); if (zoom >= 3) size += QSize(1, 1); //zwiększamy rozmiar o siatkę jeśli zoom jest >= 3 return size; } // bardzo ważna funkcja dla QTDesignera, przy tworzeniu layoutów
10
Qt::WA_StaticContents Właściwość ta powoduje, że widget jest na stałe przyczepiony do lewego górnego rogu i jego zawartość nie zmienia się podczas zmieniania jego rozmiaru. Normalnie kiedy zmieniamy rozmiar widgetu, Qt wykonuje zdarzenie Paint Event, dzięki właściwości WA_Static Contents, podczas zmniejszania PaintEvent nie jest niepotrzebnie wykonywany.
11
IconEditor.cpp void IconEditor::setPenColor(const QColor &newColor) //funkcja ustawiająca kolor { curColor = newColor; } void IconEditor::setIconImage(const QImage &newImage) //ustawia ikonę do edycji { if (newImage != image) { image = newImage.convertToFormat(QImage::Format_ARGB32);//zmieniamy format na ARGB32 update(); //Odświeżenie bitmapy updateGeometry(); //zmiana SizeHinta } void IconEditor::setZoomFactor(int newZoom) { if (newZoom < 1) newZoom = 1; if (newZoom != zoom) { zoom = newZoom; update(); updateGeometry(); }
12
PaintEvent Paint Event jest wywoływany gdy: widget jest pokazywany po raz pierwszy zmieniamy rozmiar widgetu widget był zakryty przez inne okno i następuje jego odsłonięcie Możemy także wywołać PaintEvent ręcznie używając funkcji QWidget::update() lub QWidget::re-paint().
13
IconEditor.cpp void IconEditor::paintEvent(QPaintEvent *event) { QPainter painter(this); if (zoom >= 3) { //rysujemy siatkę painter.setPen(palette().foreground().color()); // ustawiamy kolor z palety for (int i = 0; i <= image.width(); ++i) painter.drawLine(zoom * i, 0, zoom * i, zoom * image.height()); for (int j = 0; j <= image.height(); ++j) painter.drawLine(0, zoom * j, zoom * image.width(), zoom * j); } for (int i = 0; i < image.width(); ++i) { for (int j = 0; j < image.height(); ++j) { QRect rect = pixelRect(i, j); //zwraca, region który trzeba namalować if (!event->region().intersect(rect).isEmpty()) { QColor color = QColor::fromRgba(image.pixel(i, j)); painter.fillRect(rect, color);//malujemy powiększony pixel }
14
IconEditor.cpp QRect IconEditor::pixelRect(int i, int j) const { if (zoom >= 3) { return QRect(zoom * i + 1, zoom * j + 1, zoom - 1, zoom - 1); //zmniejszamy o siatkę } else { return QRect(zoom * i, zoom * j, zoom, zoom); } void IconEditor::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { setImagePixel(event->pos(), true); } else if (event->button() == Qt::RightButton) { setImagePixel(event->pos(), false); }
15
IconEditor.cpp void IconEditor::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { setImagePixel(event->pos(), true); } else if (event->buttons() & Qt::RightButton) { setImagePixel(event->pos(), false); } void IconEditor::setImagePixel(const QPoint &pos, bool opaque) { // funkcja kolorująca lub czyszcząca dany pixel int i = pos.x() / zoom; int j = pos.y() / zoom; if (image.rect().contains(i, j)) { //sprawdzamy czy punkt znajduje się na obrazku if (opaque) { image.setPixel(i, j, penColor().rgba()); //kolorujemy } else { image.setPixel(i, j, qRgba(0, 0, 0, 0)); //czyścimy } update(pixelRect(i, j)); }
16
Jak zintegrować widgety z QtDesignerem? promotion approach (Przekształcanie) plugin approach
17
Integrujemy HexSpinBox 1.Tworzymy zwykły QSpinBox 2.Klikamy prawym przyciskiem myszy i wybieramy opcję Przekształć do.. 3.Ustawiamy odpowiedni nagłówek klasy
18
Integrujemy IconEditor Musimy napisać odpowiedni plugin i zintegrować go z QtDesignerem. Zakładamy,że plugin znajduje się w katalogu iconeditorplugin,a pliki źródłówe w katalogu iconeditor. Dziedziczymy po klasie QDesignerCustomWidgetInterface i implementujemy niektóre virtualne funkcje.
19
IconEditorPlugin.h #include class IconEditorPlugin : public QObject, public QDesignerCustomWidgetInterf { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) //makro, które mówi, że dana klasa jest pluginem public: IconEditorPlugin(QObject *parent = 0); QString name() const; QString includeFile() const; QString group() const; QIcon icon() const; QString toolTip() const; QString whatsThis() const; bool isContainer() const; QWidget *createWidget(QWidget *parent); };
20
IconEditorPlugin::IconEditorPlugin(QObject *parent) //konstruktor : QObject(parent) { } QString IconEditorPlugin::name() const //Funkcja zwraca nazwę widgetu { return "IconEditor"; } QString IconEditorPlugin::includeFile() const { return "iconeditor.h"; } QString IconEditorPlugin::group() const //zwraca grupę do której dany widget powinien należeć, jeżeli nie ma takiej grupy w QtDesignerze zostanie ona stworzona { return tr("Image Manipulation Widgets"); } IconEditorPlugin.cpp
21
QIcon IconEditorPlugin::icon() const //zwraca obrazek którym widget będzie reprezentowany w QtDesignerze { return QIcon(":/images/iconeditor.png"); } QString IconEditorPlugin::toolTip() const { return tr("An icon editor widget"); } QString IconEditorPlugin::whatsThis() const { return tr("This widget is presented in Chapter 5 of C++ GUI " "Programming with Qt 4 as an example of a custom Qt " "widget."); } IconEditorPlugin.cpp
22
bool IconEditorPlugin::isContainer() const { // funkcja zwraca true jeśli na widgecie, możemy umieszczać inne widgety return false; } QWidget *IconEditorPlugin::createWidget(QWidget *parent) { return new IconEditor(parent); //funkcja tworząca obiekt klasy reprezntującej widget } Q_EXPORT_PLUGIN2(iconeditorplugin, IconEditorPlugin) //makro czyniące plugin dostępnym dla QtDesignera
23
Plik projektu Plik projektu-. pro powinien wyglądać następująco: TEMPLATE = lib CONFIG += designer plugin release HEADERS =../iconeditor/iconeditor.h \ iconeditorplugin.h SOURCES =../iconeditor/iconeditor.cpp \ iconeditorplugin.cpp RESOURCES = iconeditorplugin.qrc DESTDIR = $(QTDIR)/plugins/designer
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.