zoukankan      html  css  js  c++  java
  • Subclassing QWidget

    iconeditor.h
     1 #ifndef ICONEDITOR_H
     2 #define ICONEDITOR_H
     3 
     4 #include <QColor>
     5 #include <QImage>
     6 #include <QWidget>
     7 
     8 class IconEditor : public QWidget
     9 {
    10     Q_OBJECT
    11     Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)
    12     Q_PROPERTY(QImage iconImage READ iconImage WRITE setIconImage)
    13     Q_PROPERTY(int zoomFactor READ zoomFactor WRITE setZoomFactor)
    14 
    15 public:
    16     IconEditor(QWidget *parent = 0);
    17 
    18     void setPenColor(const QColor &newColor);
    19     QColor penColor() const { return curColor; }
    20     void setZoomFactor(int newZoom);
    21     int zoomFactor() const { return zoom; }
    22     void setIconImage(const QImage &newImage);
    23     QImage iconImage() const { return image; }
    24     QSize sizeHint() const;
    25 
    26 protected:
    27     void mousePressEvent(QMouseEvent *event);
    28     void mouseMoveEvent(QMouseEvent *event);
    29     void paintEvent(QPaintEvent *event);
    30 
    31 private:
    32     void setImagePixel(const QPoint &pos, bool opaque);
    33     QRect pixelRect(int i, int j) const;
    34 
    35     QColor curColor;
    36     QImage image;
    37     int zoom;
    38 };
    39 #endif

      Q_PROPERTY宏声明三个自定义属性:penColor,iconImage,zoomFactor。每一个属性都有一个数据类型,一个“读”函数,和一个可以选的“写”函数。比如:penColor类型是QColor,可以用penColor()和setPenColor函数进行读写。

    Q_PROPERTY(...)被用在类中声明继承自QObject的属性。这些属性就像类的数据成员一样,但是他们通过Meta-Object System具有附加的特性。

     Q_PROPERTY(type name
                READ getFunction
                [WRITE setFunction]
                [RESET resetFunction]
                [NOTIFY notifySignal]
                [DESIGNABLE bool]
                [SCRIPTABLE bool]
                [STORED bool]
                [USER bool]
                [CONSTANT]
                [FINAL])
    
    
    属性名字、类型和READ函数是必须的。类型可以是任何QVariant支持的类型,或用户自定义类型。其他项是可选的,但是通常都有WRITE函数。这些属性的默认值都为true,除了USER是false。

    The Meta-Object System

    Meta-Object系统基于以下三点:

    1、QObject类为目标类提供基类以支持这个目标类利用Meta-Object系统。

    2、类声明中必须有O_OBJECT宏,使能Meta-Object的属性,如:动态属性、信号、槽。

    3、Meta-Object Compiler(moc)为每个QObject的子类华提供必要代码以实现meta-object特性。

      IconEditor重实现了三个QWidget的protected function:mousePressEven,mouseMoveEvent,paintEvent。 三个私有变量保存前面定义的三个属性的值。

    iconeditor.cpp
     1 #include <QtGui>
     2 
     3 #include "iconeditor.h"
     4 
     5 IconEditor::IconEditor(QWidget *parent)
     6     : QWidget(parent)
     7 {
     8     setAttribute(Qt::WA_StaticContents);
     9     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    10 
    11     curColor = Qt::black;
    12     zoom = 8;
    13 
    14     image = QImage(16, 16, QImage::Format_ARGB32);
    15     image.fill(qRgba(0, 0, 0, 0));
    16 }

      pen color设为黑色,zoom设为8,意味着在icon中每个像素为8X8的正方形。

      icon数据保存在i,mage成员变量中,可以通过setIconImage()、iconImage()函数访问。一个icon编辑程序通常在打开一个icon文件时调用setIconImage(),在保存时调用iconImage()去读回icon(原句retrieve the icon)。

      QImage可以把图像存为1-bit,8-bit,32-bit depth。 32位用8位分别表示红、绿、蓝,剩下的8位表示透明度。比如纯红色:255,0,0,255。

    QRgb red = qRgba(255, 0, 0, 255);

    或者颜色为不透明的

    QRgb red = qRgb(255, 0, 0);

    QRgb即是unsigned int, qRgb() 和 qRgb()都是用来把它们组成一个32位的ARGB整数值的内嵌函数。也可以写成如下形式:

    QRgb red = 0xFFFF0000;

    Qt提供QRgb 和QColor两种类型存储颜色。但是QRgb只用在QImage中存储32位像素的别名,QColor用途则更广泛。

    iconeditor.cpp
     1 QSize IconEditor::sizeHint() const
     2 {
     3     QSize size = zoom * image.size();
     4     if (zoom >= 3)
     5         size += QSize(1, 1);
     6     return size;
     7 }
     8 
     9 void IconEditor::setPenColor(const QColor &newColor)
    10 {
    11     curColor = newColor;
    12 }
    13 
    14 void IconEditor::setIconImage(const QImage &newImage)
    15 {
    16     if (newImage != image) {
    17         image = newImage.convertToFormat(QImage::Format_ARGB32);
    18         update();
    19         updateGeometry();
    20     }
    21 }
    22 
    23 void IconEditor::setZoomFactor(int newZoom)
    24 {
    25     if (newZoom < 1)
    26         newZoom = 1;
    27 
    28     if (newZoom != zoom) {
    29         zoom = newZoom;
    30         update();
    31         updateGeometry();
    32     }
    33 }

    sizeHint()是从QWidget中重新实现的。用图像的大小乘以缩放因子作为窗口部件的理想大小,如果缩放因子大于等于3,则向每个方向增加一个像素,以容纳网格线(如果是2或1则网络线会占据大部分空间,以至像素可以忽略)。
    QWidget::update() 使用新的图像强制重绘这个窗口部件,但是这个函数不立即重绘,而是产生一人下paint event ,让Qt返回主事件循环时执行。

    QWidget::updateGeometry()告诉包含这个窗口部件的任意布局,这个窗口大小已经改变。

    iconeditor.cpp
     1 void IconEditor::paintEvent(QPaintEvent *event)
     2 {
     3     QPainter painter(this);
     4     if (zoom >= 3) {
     5         painter.setPen(palette().foreground().color());
     6         for (int i = 0; i <= image.width(); ++i)
     7             painter.drawLine(zoom * i, 0,
     8                              zoom * i, zoom * image.height());
     9         for (int j = 0; j <= image.height(); ++j)
    10             painter.drawLine(0, zoom * j,
    11                              zoom * image.width(), zoom * j);
    12     }
    13     for (int i = 0; i < image.width(); ++i) {
    14         for (int j = 0; j < image.height(); ++j) {
    15             QRect rect = pixelRect(i, j);
    16             if (!event->region().intersect(rect).isEmpty()) {
    17                 QColor color = QColor::fromRgba(image.pixel(i, j));
    18                 if (color.alpha() < 255)
    19                     painter.fillRect(rect, Qt::white);
    20                 painter.fillRect(rect, color);
    21             }
    22         }
    23     }
    24 }
    25 
    26 QRect IconEditor::pixelRect(int i, int j) const
    27 {
    28     if (zoom >= 3) {
    29         return QRect(zoom * i + 1, zoom * j + 1, zoom - 1, zoom - 1);
    30     } else {
    31         return QRect(zoom * i, zoom * j, zoom, zoom);
    32     }
    33 }

    Qt中很多情况下都会产生绘制事件,调用paintEvent()函数:

    1.         当控件第一次显示时,Qt自动产生绘制事件强制控件绘制自身。
    2.         当控件尺寸发生变化时,系统产生绘制事件
    3.         如果控件被其他的窗口遮住,窗口移走再现时,产生绘制被遮住部分的事件。

    一个窗口部件的调色板由三个颜色组构成:Active, Inactive, Disabled 

    Active 可用于当前激活窗口中的那些窗口部件。

    Inactive可用于其他窗口中的那些窗口头部件。

    Disabled可用于任意窗口中的那些不可用的窗口部件。

    QWidgt::paletet()函数返回窗口部件的调色板,它是一个QPalette型对象。

    foreground()是Qt3支持的QColorGroup成员,QPalette::foreground()返回一个画笔。

    IconEditor::pixelRect()返回一个QRect,其中定义了需要重新绘制的区域。

    const QRegion & QPaintEvent::region() const返回一个需要更新的区域。

    QRegion QRegion::intersect ( const QRegion & r ) const

    intersect()是QRegion废弃的成员,新的为:

    QRegion QRegion::intersected ( const QRect & rect ) const

    返回该区域与给定Rect相交的部分。

    bool QRegion::isEmpty () const

    QRegion r1(10, 10, 20, 29);

    r1.isEmpty();                             //false

    QRegion r3;

    r3.isEmpty();          // true

    QRegionr2(40, 40, 20, 20);

    r3 = r1.intersected(r2);      //r3: intersection(交叉) of r1 and r2

    r3.isEmpty();          //false

    r3 = r1.united(r2);       // r3:union of r1 and r2

    r3.isEmpty();          /false

    QColor QColor::fromRgba ( QRgb rgba ) [static]

    把rgba值变成QColor ,QRgb QImage::piixel(const QPoint & position) const 返回给定位置像素的颜色,如果该位置无效,则返回值未定义。

    void QPainter::fillRect ( const QRectF & rectangle, const QBrush & brush )

    用指定的brush填充指定的区域。painter.fillRect(rect,color);即是将载入的图像画在窗口部件指定区域上。

       综上所述,只需要void IconEditor::setIconImage(const QImage &newImage);    void paintEvent(QPaintEvent *event);   QRect pixelRect(inti, intj) const; 就可以把":/images/mouse.png"显示在窗口部件上:

      1、main函数中调用 setIconImage()载入图片。

      2、在第一次显示窗口时产生paint event。

      3、主程序循环时,处理paint event,调用paintEvent()绘图(在这个函数中用到pixelRect()定位要绘制的区域)。

    iconeditor.cpp
     1 void IconEditor::mousePressEvent(QMouseEvent *event)
     2 {
     3     if (event->button() == Qt::LeftButton) {
     4         setImagePixel(event->pos(), true);
     5     } else if (event->button() == Qt::RightButton) {
     6         setImagePixel(event->pos(), false);
     7     }
     8 }
     9 
    10 void IconEditor::mouseMoveEvent(QMouseEvent *event)
    11 {
    12     if (event->buttons() & Qt::LeftButton) {
    13         setImagePixel(event->pos(), true);
    14     } else if (event->buttons() & Qt::RightButton) {
    15         setImagePixel(event->pos(), false);
    16     }
    17 }
    18 
    19 void IconEditor::setImagePixel(const QPoint &pos, bool opaque)
    20 {
    21     int i = pos.x() / zoom;
    22     int j = pos.y() / zoom;
    23 
    24     if (image.rect().contains(i, j)) {
    25         if (opaque) {
    26             image.setPixel(i, j, penColor().rgba());
    27         } else {
    28             image.setPixel(i, j, qRgba(0, 0, 0, 0));
    29         }
    30         update(pixelRect(i, j));
    31     }
    32 }

      以上三个函数用于响应鼠标事件,用鼠标绘制图

    main.cpp
     1 #include <QApplication>
     2 
     3 #include "iconeditor.h"
     4 
     5 int main(int argc, char *argv[])
     6 {
     7     QApplication app(argc, argv);
     8     IconEditor iconEditor;
     9     iconEditor.setWindowTitle(QObject::tr("Icon Editor"));
    10     iconEditor.setIconImage(QImage(":/images/mouse.png"));
    11     iconEditor.show();
    12     return app.exec();
    13 }

     

     

  • 相关阅读:
    sencha touch 扩展篇之将sencha touch打包成安装程序(上)- 使用sencha cmd打包安装程序
    sencha touch 扩展篇之使用sass自定义主题样式 (下)通过css修改官方组件样式以及自定义图标
    一个不错的android组件的网站
    sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式
    sencha touch 入门系列 (九) sencha touch 布局layout
    面试题总结
    国外接活网站Elance, Freelancer和ScriptLance的介绍和对比
    sencha touch 入门系列 扩展篇之sencha touch 项目打包压缩
    Android Design Support Library——Navigation View
    设计模式——命令模式
  • 原文地址:https://www.cnblogs.com/lucheng/p/2820756.html
Copyright © 2011-2022 走看看