找回密码
 立即注册
收起左侧

第15篇 Qt5之2D绘图(五)绘制图片

9
回复
10952
查看
[复制链接]
累计签到:1564 天
连续签到:1 天
来源: 2017-4-1 17:06:07 显示全部楼层 |阅读模式
版权声明


该文章原创于Qt开源社区(www.qter.org),作者yafeilinux,转载请注明出处!


导语


Qt提供了四个类来处理图像数据:QImageQPixmapQBitmapQPicture,它们都是常用的绘图设备。其中QImage主要用来进行I/O处理,它对I/O处理操作进行了优化,而且可以用来直接访问和操作像素;QPixmap主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;QBitmapQPixmap的子类,用来处理颜色深度为1的图像,即只能显示黑白两种颜色;QPicture用来记录并重演QPainter命令。这一节我们只讲解QPixmap



环境:Windows 7 + Qt 5.8.0(包含Qt Creator 4.2.1)



目录


一、简单绘制图片
二、平移图片
三、缩放图片
四、旋转图片
五、扭曲图片



正文



一、简单绘制图片


1.这次我们重新创建一个Qt Widgets应用,项目名称为mypixmap,在类信息页面,将基类选择为QDialog,类名使用默认的Dialog即可。


2.然后在源码目录中复制一张图片,比如这里是一张logo.png图片,如下图所示。



3.dialog.h文件中添加重绘事件处理函数的声明:

protected:
    void paintEvent(QPaintEvent *);


4.dialog.cpp文件中先添加头文件包含#include <QPainter>,然后添加函数的定义:

void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load("../mypixmap/logo.png");
    painter.drawPixmap(0, 0, 80, 100, pix);
}

        这里使用了相对路径,因为Qt Creator默认是使用影子构建,即编译生成的文件在build-mypixmap-Desktop_Qt_5_8_0_MinGW_32bit-Debug这样的目录里面,而这个目录就是当前目录,所以源码目录就是其上级目录了。大家可以根据自己的实际情况来更改路径,也可以使用绝对路径,不过最好使用资源文件来存放图片。drawPixmap()函数在给定的矩形中来绘制图片,这里矩形的左上角顶点为(0, 0)点,宽80,高100,如果宽高跟图片的大小比例不同,默认会拉伸图片。运行效果如下图所示。




(注意:下面的操作涉及到了坐标系统,这里不会详细讲解,大家先进行操作查看效果,具体的坐标内容将在下一节讲解。)


二、平移图片


        QPainter类中的translate()函数实现坐标原点的改变,改变原点后,此点将会成为新的原点(00。下面来看一个例子。paintEvent()函数里面继续添加如下代码:


//将(100,100)设为坐标原点
painter.translate(100, 100);
painter.drawPixmap(0, 0, 80, 100, pix);


        运行程序,效果如下图所示。



这里将(100100)设置为了新的坐标原点,所以下面在(00)点贴图,就相当于在以前的(100100)点贴图。



三、缩放图片


        我们可以使用QPixmap类中的scaled()函数来实现图片的放大和缩小。paintEvent()函数中继续添加代码:


//获得以前图片的宽和高
qreal width = pix.width();
qreal height = pix.height();
//将图片的宽和高都缩小,并且在给定的矩形内保持宽高的比值不变
pix = pix.scaled(width*0.2, height*0.2,
                 Qt::KeepAspectRatio);
painter.drawPixmap(90, 90, pix);

其中参数Qt::KeepAspectRatio,是图片缩放的方式。我们可以查看其帮助。将鼠标指针放到该代码上,当出现F1提示时,按下F1键,这时就可以查看其帮助了。当然我们也可以直接在帮助里索引该关键字。如下图所示。


这里有三个值,只看其示例图片就可大致明白,Qt::IgnoreAspectRatio是不保持图片的宽高;Qt::KeepAspectRatio是在给定的矩形中保持宽高最后一个也是保持宽高比,但可能超出给定的矩形。这里给定的矩形是由我们显示图片时给定的参数决定的,例如painter.drawPixmap(0,0,100,100,pix);就是在以(00)点为起始点的宽和高都是100的矩形中。运行程序效果如下图所示。




四、旋转图片


        旋转使用的是QPainter类的rotate()函数,它默认是以原点为中心进行旋转的。如果要改变旋转的中心,可以使用前面讲到的translate()函数完成。
paintEvent()函数中继续添加如下代码:

//让图片的中心作为旋转的中心
painter.translate(40, 50);
painter.rotate(90); //顺时针旋转90度
painter.translate(-40,-50); //使原点复原
painter.drawPixmap(100, 100, 80, 100, pix);

        这里必须先改变旋转中心,然后再旋转,然后再将原点复原,才能达到想要的效果。运行程序,如下图所示。




五、扭曲图片


        实现图片的扭曲,是使用的QPainter类的shear(qreal sh,qreal sv)函数完成的。它有两个参数,前面的参数实现横向变形,后面的参数实现纵向变形。当它们的值为0时,表示不扭曲。
paintEvent()中继续添加如下代码:


painter.shear(0.5, 0); //横向扭曲
painter.drawPixmap(100, 0, 80, 100, pix);


运行效果如下图所示。



结语



这一节中只讲解了QPixmap类的简单应用。对于后面讲到的图片变形的应用,细心的读者可能已经发现了,旋转了坐标系统以后再绘制图片都是纵向的,这就是因为旋转了坐标系统而没有进行恢复造成的。具体的坐标操作我们会在下一节讲解。

源码下载:






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

累计签到:9 天
连续签到:1 天
2017-4-5 23:06:38 显示全部楼层
飞哥,为啥我这在应用程序输出提示“QPixmap::scaled: Pixmap is a null pixmap”,我拿了你的源程序也是这个问题,没搞定。。。
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2017-4-6 15:45:25 显示全部楼层
v786171161 发表于 2017-4-5 23:06
飞哥,为啥我这在应用程序输出提示“QPixmap::scaled: Pixmap is a null pixmap”,我拿了你的源程序也是这 ...

看下图片路径对不对
回复 支持 反对

使用道具 举报

累计签到:9 天
连续签到:1 天
2017-4-6 21:23:57 显示全部楼层
构建目录错了。。。麻烦啦!
回复 支持 反对

使用道具 举报

累计签到:14 天
连续签到:1 天
2017-6-4 11:54:12 显示全部楼层
飞哥,我的在第一个加载图片就失败了(相对路径下,绝对路径没问题),图加载不出来,但是运行你的却能加载出来,怎么办?
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2017-6-6 10:34:37 显示全部楼层
johnrambos 发表于 2017-6-4 11:54
飞哥,我的在第一个加载图片就失败了(相对路径下,绝对路径没问题),图加载不出来,但是运行你的却能加载 ...

你的相对路径确保没有写错吗?
回复 支持 反对

使用道具 举报

累计签到:29 天
连续签到:1 天
2017-9-22 17:35:42 显示全部楼层
johnrambos 发表于 2017-6-4 11:54
飞哥,我的在第一个加载图片就失败了(相对路径下,绝对路径没问题),图加载不出来,但是运行你的却能加载 ...

我也是这样的
第一次相对路径不行
就把Qt关了重新打开
用绝对路径,是可以的
改成相对路径 又可以了
不知道为什么
回复 支持 反对

使用道具 举报

累计签到:14 天
连续签到:1 天
2019-2-27 20:36:00 显示全部楼层
亚飞老师,我想问一下,
pix = pix.scaled(width*0.2, height*0.2,
                 Qt::KeepAspectRatio);
这里的0.2扩大的目标是图片本身的大小还是插入程序中后的大小。
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2019-2-27 21:57:02 显示全部楼层
staticnull 发表于 2019-2-27 20:36
亚飞老师,我想问一下,
pix = pix.scaled(width*0.2, height*0.2,
                 Qt::KeepAspectRatio) ...

我感觉这个可以自己想办法找到答案。
回复 支持 反对

使用道具 举报

累计签到:14 天
连续签到:1 天
2019-2-28 13:46:31 显示全部楼层
yafeilinux 发表于 2019-2-27 21:57
我感觉这个可以自己想办法找到答案。

:D:D:D:D:D:D:D:D
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了