1 / 23

Rozdział 5 „Creating custom widgets”

Rozdział 5 „Creating custom widgets”. Autor: Bartłomiej Suliga. Przekształcanie istniejących widgetów. HexSpinBox- spin box z wartościami w notacji szesnastkowej Dziedziczymy po klasie QSpinBox Implementujemy niektóre metody. HexSpinBox.h. #ifndef HEXSPINBOX_H

efia
Download Presentation

Rozdział 5 „Creating custom widgets”

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 <QSpinBox> 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 <QtGui> //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 <QColor> #include <QImage> #include <QWidget> 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 <QtGui> #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 <QDesignerCustomWidgetInterface> 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.cpp 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"); }

  21. IconEditorPlugin.cpp 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 <i>C++ GUI " "Programming with Qt 4</i> as an example of a custom Qt " "widget."); }

  22. IconEditorPlugin.cpp 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

More Related