• 《QT Creator快速入门》第十章:2D绘制(3)


    1、绘制文字

        使用QPainter::drawText()来绘制文字:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
    
        QRectF rect(10.0, 10.0, 580.0, 280.0);
        painter.setPen(Qt::red);
        painter.drawRect(rect);
    
        painter.setPen(Qt::blue);
        painter.drawText(rect, Qt::AlignHCenter, "alignHCenter");
        painter.drawText(rect, Qt::AlignLeft, "alignLeft");
        painter.drawText(rect, Qt::AlignRight, "alignRight");
        painter.drawText(rect, Qt::AlignVCenter, "alignVCenter");
        painter.drawText(rect, Qt::AlignBottom, "AlignBottom");
        painter.drawText(rect, Qt::AlignCenter, "AlignCenter");
        painter.drawText(rect, Qt::AlignBottom | Qt::AlignRight, "AlignBottom|AlignRight");
        painter.drawText(rect, Qt::AlignBottom | Qt::AlignCenter, "AlignBottom|AlignCenter");
        painter.drawText(rect, Qt::AlignCenter | Qt::AlignRight, "AlignCenter|AlignRight");
    }
    View Code

        

        使用QPainter::setFont()来设置文字字体,QPainter::fontInfo()可以获得当前字体信息,QFontDatabase类可以获得支持的所有字体族:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
    
        QFont font("宋体", 15, QFont::Bold, true); //字体族,磅值,字体粗细,是否斜体
        font.setUnderline(true);//设置下划线
        font.setCapitalization(QFont::AllUppercase);//设置字母大写
        font.setLetterSpacing(QFont::AbsoluteSpacing, 10);//设置字符间距
    
        painter.setFont(font);
        painter.setPen(Qt::green);
        painter.drawText(120, 80, "yafei-linux");
    
        //平移并旋转后再绘制文本
        painter.translate(120, 100);
        painter.rotate(90);
        painter.drawText(0, 0, "hello qt");
    }
    View Code

         

        drawText()还有一个以一个点为基准来绘制文本的版本,如下所示,需要注意的是绘制的时候是以这个点的Y坐标为字体的baseline的:

        

    2、绘制图片

        Qt提供了四个类来处理图像数据:QImage、QPixmap、QBitmap、QPicture。

        ①、QImage不仅可以加载一个图片然后显示出来,还可以在一个QImage上进行绘制文字,图形等操作,然后将这个QImage显示出来,如以下代码在QImage上进行一些绘制操作,然后显示出来:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter;
        QImage image(100, 100, QImage::Format_ARGB32);
    
        painter.begin(&image);
        painter.setPen(QPen(Qt::green, 3));
        painter.setBrush(Qt::yellow);
        painter.drawRect(10, 10, 60, 60);
        painter.drawText(10, 10, 60, 60, Qt::AlignCenter, "QImage");
        painter.setBrush(QColor(0, 0, 0, 100));
        painter.drawRect(50, 50, 40, 40);
        painter.end();
    
        painter.begin(this);
        painter.drawImage(50, 20, image);
        painter.end();
    }
    View Code

         

        下面代码实现了加载图片然后显示,再将图片特殊处理后显示并另存为的功能:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
    
        QImage image;
        image.load("F://image.png");//加载图片
        qDebug() << "size: " << image.size() << "format: " << image.format() << "depth: " << image.depth();//获得图片信息
        painter.drawImage(10, 10, image);//显示图片
    
        QImage mirror = image.mirrored();//获取图片镜像
        QTransform transform;
        transform.shear(0.2, 0);
        QImage image2 = mirror.transformed(transform);//将图片扭曲
        painter.drawImage(300, 10, image2);//显示图片
        image2.save("F://image2.png");//保存图片
    }
    View Code

        

        QImage还提供了强大的访问和操作像素的功能。

         ②、一般是使用QPixmap加载和显示 图像,如果需要提前对图像进行操作的话,先用QImage加载图片,对图片数据进行操作,然后将Qimage转换为QPixmap对象来显示图片(可以使用toImage()和fromImage()在QImage和QPixmap之间进行转换)。

               QPixmap的fill()函数可以使用指定的颜色初始化整个pixmap图像,还可以使用grabWindows()和grabWidget()等静态函数来实现截取屏幕、截取窗口部件上内容功能。

        以下代码使用QPixmap加载并显示了图片,并展示了在图片之上绘制一个透明矩形的效果:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
        QPixmap pix;
        pix.load("./image.png");
        painter.drawPixmap(0, 0, pix);
    
        painter.drawPixmap(300, 0, pix);
        painter.setBrush(QColor(255, 255, 255, 100));
        painter.drawRect(300, 0, pix.width(), pix.height());
    
        painter.drawPixmap(0, 250, pix);
        painter.setBrush(QColor(0, 0, 255, 100));
        painter.drawRect(0, 250, pix.width(), pix.height());
    
        painter.drawPixmap(300, 250, pix);
        painter.setBrush(QColor(0, 0, 0, 150));
        painter.drawRect(300, 250, pix.width(), pix.height());
    }
    View Code

             

            drawPixmap()有很多重载函数,比如:

            void QPainter::drawPixmap ( int x, int y, const QPixmap & pixmap ),表示使用pixmap中图片大小向(x, y)处绘制。

            void QPainter::drawPixmap ( int x, int y, int width, int height, const QPixmap & pixmap ),表示向指定坐标和大小的位置绘制 pixmap中内容

            void QPainter::drawPixmap ( int x, int y, const QPixmap & pixmap, int sx, int sy, int sw, int sh ),表示向指定坐标绘制pixmap中指定位置和大小的内容。

            下面的代码截取整个屏幕后保存文件,然后将截取的图像显示到一个Label上:

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        QPixmap screen = QPixmap::grabWindow(QApplication::desktop()->winId());
        screen.save("F://screen.png");
    
        QLabel* label = new QLabel(this);
        label->move(10, 10);
    
        label->resize(400, 200);
        QPixmap pix = screen.scaled(label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        label->setPixmap(pix);
    }
    View Code

            

              上面代码用到了QPixmap::scaled()函数,它可以对QPixmap上图像进行缩放后保存到另一个QPixmap对象上,其第一个参数指定缩放后的大小,第二个参数指定宽高比(Qt::IgnoreAspectRatio为自由缩放;Qt::KeepAspectRatio为保持宽高比,在给定的矩形内;Qt::KeepAspectRatioByExpanding为保持宽高比,在给定的矩形外;各选项效果见下图),第三个参数指定转换模式(快速转换Qt::FastTransformation和平滑转换Qt::SmoothTransformation) 。

              

        ③、QBitmap只能用来处理和显示黑白两种颜色。

        ④、QPicture是一个可以记录和重演QPainter命令的绘图设备,即它可以将绘图命令序列化,对序列化的绘图命令进行重演。

        ⑤、使用QPainter::setCompositionMode()来设置绘图的复合模式,其中有QPainter::CompositionMode_SourceOver(默认模式)、QPainter::CompositionMode_DestinationOver等模式,各模式效果如下图:

             

             修改绘图的复合模式一个示例及效果:

    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter;
        QImage image(400, 300, QImage::Format_ARGB32_Premultiplied);
        painter.begin(&image);
    
        painter.setBrush(Qt::red);
        painter.drawRect(100, 50, 200, 200);
    
        painter.setBrush(Qt::green);
        painter.drawRect(50, 0, 100, 100);
    
        painter.setBrush(Qt::blue);
        painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
        painter.drawRect(250, 0, 100, 100);
    
        painter.end();
        painter.begin(this);
        painter.drawImage(0, 0, image);
        painter.end();
    }
    View Code

            

     可以将图片添加到项目中来使用,添加图片资源的方法为:首先项目右键添加Qt资源文件(名称可以设置为myResource,路径为当前项目目录,点击确定后可以看到当前项目下有了一个qrc文件)->如果没有弹出资源编辑器页面的话右键点击qrc文件选择open in editor,然后点击下方的“添加”按钮,选择添加前缀,可以编辑前缀名为/image,按下ctrl+s保存->然后再点击下方的"添加"按钮,选择添加文件来添加图片文件(图片文件应该在qrc所在目录下或其子目录下),最后按下ctrl+s保存,然后在程序中就可以通过":/image/imageName.png"来使用图片:

    void Widget::paintEvent(QPaintEvent* )
    {
        QPainter painter(this);
        QPixmap pix(":/image/112.png");
        painter.drawPixmap(0, 0, pix);//在指定位置chu 原图大小显示
        //painter.drawPixmap(QRect(10, 10, 200, 160), pix,
        //                   QRect(0, 0, pix.width(), pix.height()));//按照指定区域缩放显示
    }
    View Code

    3、其它图像处理类

    QImageReader可以在加载图像时提供更多的控制,如使用setScaledSize()来将图像以指定的大小来读取,使用setClipRect()来只读取图像的一个区域。

    QImageWriter提供了保存图像的更多控制,如压缩等级和品质、伽玛等级等。

    QMovie可以用来播放gif动画,可以参考该类的帮助文档或查看Movie Player示例程序。

    QSvgWidget可以加载一个SVG(可缩放矢量图形)文件,使用QSvgRenderer类在QSvgWidget中进行SVG文件的渲染,可以参考SVG Generator和SVG Viewer示例程序。

    4、键盘事件鼠标事件、重绘事件

       键盘按下事件处理函数:void keyPressEvent(QKeyEvent *);

       键盘松开事件处理函数:void keyReleaseEvent(QKeyEvent *)

    鼠标按下事件处理函数:mousePressEvent(QMouseEvent* event)
    鼠标移动事件处理函数:mouseMoveEvent(QMouseEvent* event),如果想要保证不用按下鼠标也能触发鼠标移动事件,则在部件的构造函数中添加:setMouseTracking(true);
    鼠标松开事件处理函数:mouseReleaseEvent(QMouseEvent* event)
    鼠标滚轮滚动事件处理函数:wheelEvent(QWheelEvent *)
    其中的QMouseEvent包含了鼠标信息,比如QMouseEvent::pos()可以获得当前鼠标位置。
    重绘事件处理函数:void Widget::paintEvent(QPaintEvent *event)
    重绘事件一般产生在repaint()或update()函数调用后,或者隐藏的部件被显示,或者其他一些原因。repaint()后paintEvent()会立即调用,update()会将重绘事件放入主消息循环中,如果update被调用了很多次,最后这些update会合并到一个大的重绘事件,所以只会调用一次update(),

    一般情况下我们选择使用update()。
    当重绘事件发生时,要更新的区域一般会被擦除,然后在部件的背景上进行绘制,部件的背景可以使用setBackgroundRole()函数来设置,然后使用setAutoFillBackground()函数来启用指定的颜色,eg:
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        
        ui->pushButton->setBackgroundRole(QPalette::Dark);
        ui->pushButton->setAutoFillBackground(true);
        
    }
    View Code

     5、双缓冲

      双缓冲绘图就是在绘制的时候将所有内容都绘制到一个绘图设备(如QPixmap)上,然后再将绘图设备中整个图像绘制到部件上显示出来,这样避免了一个一个的将内容绘制到部件上产生的显示闪烁现象。Qt4之后QWidget部件的所有绘制都自动使用了双缓冲,所以一般没必要在paintEvent()中使用双缓冲,不如如果想要实现一些绘图效果的话,还是要借助双缓冲的概念。

  • 相关阅读:
    VMwareTools安装+CentOS分辨率调整
    WSDL文件示例及说明
    CentOS 5.4 服务器配置 yum安装Apache+php+Mysql+phpmyadmin
    linuxVi使用方法(备查)
    C++ 泛型算法定制操作
    C++ 迭代器分类
    求最长回文串的长度
    C++ 关联容器
    html标签之label
    转载div+css命名规范标准
  • 原文地址:https://www.cnblogs.com/milanleon/p/7344490.html
Copyright © 2020-2023  润新知