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

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

37
回复
40323
查看
[复制链接]
累计签到:1564 天
连续签到:1 天
来源: 2013-5-2 17:59:00 显示全部楼层 |阅读模式
绘制图片

版权声明

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



导语

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




环境:Windows Xp + Qt 4.8.4+QtCreator 2.6.2



目录

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




正文


一、简单绘制图片


1.这次我们重新创建一个Qt Gui应用,项目名称为painter_2,在类信息页面,将基类更改为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("../painter_2/logo.png");
    painter.drawPixmap(0, 0, 129, 66, pix);
}
    这里使用了相对路径,因为Qt Creator默认是使用影子构建,即编译生成的文件在painter_2-build-desktop-Debug这样的目录里面,而这个目录就是当前目录,所以源码目录就是其上级目录了。大家可以根据自己的实际情况来更改路径,也可以使用绝对路径,不过最好使用资源文件来存放图片。drawPixmap()函数在给定的矩形中来绘制图片,这里矩形的左上角顶点为(0, 0)点,宽129,高66,如果这个跟图片的大小不相同,默认会拉伸图片。运行效果如下图所示。

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

二、平移图片

QPainter类中的translate()函数实现坐标原点的改变,改变原点后,此点将会成为新的原点(00)。下面来看一个例子。

paintEvent()函数里面继续添加如下代码:

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

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

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



三、缩放图片

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


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

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


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



四、旋转图片


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

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

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




五、扭曲图片


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


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

运行效果如下图所示。



结语

       这一节中只讲解了QPixmap类的简单应用。对于后面讲到的图片变形的应用,细心的读者可能已经发现了,旋转了坐标系统以后再绘制图片都是纵向的,这就是因为旋转了坐标系统而没有进行恢复造成的。具体的坐标操作我们会在下一节讲解。
       如果大家还想系统的学习其他绘图类的应用,可以参考《Qt Creator快速入门》10章的相关内容。




涉及到的源码:



上一篇:  第14篇 2D绘图(四)绘制路径

下一篇:  第16篇 2D绘图(六)坐标系统

返回:系列教程目录   


本帖子中包含更多资源

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

x
参与人数 1人气 +2 收起 理由
ellen + 2 对我帮助很大!

查看全部评分总评分 : 人气 +2

回复

使用道具 举报

累计签到:2 天
连续签到:1 天
2013-6-23 22:42:41 显示全部楼层
遇到一点小问题,我在creator里面debug程序时,能够显示绘制的图片,但是我到debug目录下双击运行painter_2.exe的时候,绘制的图片不能显示。哪位大神知道为什么?
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2013-6-23 22:44:25 显示全部楼层
tuqiao820 发表于 2013-6-23 22:42
遇到一点小问题,我在creator里面debug程序时,能够显示绘制的图片,但是我到debug目录下双击运行painter_2 ...

应该是路径问题,你再看看
回复 支持 反对

使用道具 举报

累计签到:2 天
连续签到:1 天
2013-6-25 14:02:50 显示全部楼层
是路径问题。生成的exe文件在painter_2-build-desktop-Debug文件夹里面的debug文件夹里。谢谢yafeilinux。
回复 支持 反对

使用道具 举报

累计签到:7 天
连续签到:1 天
2014-3-10 23:23:29 显示全部楼层
如何在QMainWindow下使用QPainter来画图?
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2014-3-12 11:23:54 显示全部楼层
Jack-Lee 发表于 2014-3-10 23:23
如何在QMainWindow下使用QPainter来画图?

重新实现paintEvent(),在里面可以随意绘制的。http://www.qter.org/forum.php?mod=viewthread&tid=91
回复 支持 反对

使用道具 举报

累计签到:7 天
连续签到:1 天
2014-3-12 20:58:45 显示全部楼层
yafeilinux 发表于 2014-3-12 11:23
重新实现paintEvent(),在里面可以随意绘制的。http://www.qter.org/forum.php?mod=viewthread&tid=91 ...

绘制简单的图像好说,绘制图片怎么弄?
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2014-3-18 09:37:34 显示全部楼层
Jack-Lee 发表于 2014-3-12 20:58
绘制简单的图像好说,绘制图片怎么弄?

你不是说要画图,而是显示图片吗?可以用QPainter的drawImage()
回复 支持 反对

使用道具 举报

累计签到:7 天
连续签到:1 天
2014-3-20 21:54:12 显示全部楼层
yafeilinux 发表于 2014-3-18 09:37
你不是说要画图,而是显示图片吗?可以用QPainter的drawImage()

多谢啦啦啦啦啦啦。。。。。。。。。。。。。。。。。。(这字符限制有点烦人,很简单的一句话,弄得我加这么多废话)
回复 支持 反对

使用道具 举报

累计签到:4 天
连续签到:1 天
2014-5-4 15:12:42 显示全部楼层
十分感谢。我只是个新手,。但是老师又要我们自学做项目。。烦恼,只能不断看资料
回复 支持 反对

使用道具 举报

累计签到:21 天
连续签到:1 天
2015-2-13 17:40:03 显示全部楼层
请问如何实现裁剪图片,比如我要现实800*600中0,0到100,100的部分
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2015-2-14 20:39:01 显示全部楼层
Infinity 发表于 2015-2-13 17:40
请问如何实现裁剪图片,比如我要现实800*600中0,0到100,100的部分

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pixmap(":/01.png");
    QPixmap pix = pixmap.copy(0, 0, 100, 100);
    p.drawPixmap(0,0,100,100,pix);
}
回复 支持 反对

使用道具 举报

累计签到:21 天
连续签到:1 天
2015-2-17 14:29:31 显示全部楼层
您好我又遇到问题啦,
我把程序发给别人,用文中的方法绘制的图片不能显示。
图片是加在资源文件中的。
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2015-2-18 18:20:42 显示全部楼层
Infinity 发表于 2015-2-17 14:29
您好我又遇到问题啦,
我把程序发给别人,用文中的方法绘制的图片不能显示。
图片是加在资源文件中的。 ...

你用什么格式的图片啊。
回复 支持 反对

使用道具 举报

累计签到:21 天
连续签到:1 天
2015-2-19 19:26:34 显示全部楼层
yafeilinux 发表于 2015-2-18 18:20
你用什么格式的图片啊。

jpg
  1.     QPainter painter(this);
  2. QPixmap pix;
  3. pix.load(":/res/img/name.jpg");
  4. painter.drawPixmap(-100, -50, 600, 327, pix);
复制代码
回复 支持 反对

使用道具 举报

累计签到:1564 天
连续签到:1 天
2015-2-20 23:04:11 显示全部楼层
Infinity 发表于 2015-2-19 19:26
jpg

需要将Qt安装目录下面的plugins目录下的imageformats目录复制过来,里面包含qjpeg4.dll即可。Qt默认只支持png格式,如果用png格式就不需要这样做了。
回复 支持 反对

使用道具 举报

累计签到:10 天
连续签到:1 天
2015-6-1 22:26:51 显示全部楼层
麻烦问一下:纯代码实现显示图片,图片未显示,难道必须生成 ui 才能显示吗
void Dialog:aintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pixmap;
    pixmap.load(tr(":/MyImage/image/doneandnext.png"));
    painter.drawPixmap(0, 0, 100, 100, pixmap);
//    painter.drawLine(QPointF(1, 1), QPointF(200, 200));
}
回复 支持 反对

使用道具 举报

累计签到:10 天
连续签到:1 天
2015-6-1 22:28:24 显示全部楼层
不知怎么多了一个表情
回复 支持 反对

使用道具 举报

累计签到:10 天
连续签到:1 天
2015-6-1 22:51:18 显示全部楼层
找到问题了,paintEvent() 我写成了PaintEvent()
回复 支持 反对

使用道具 举报

累计签到:256 天
连续签到:1 天
2015-8-15 09:29:51 显示全部楼层
我想问问 为什么图像旋转的时候painter.drawPixmap(100, 100, 129, 66, pix);会到左下角的位置
使用90°旋转时候,图像的移动方式也变了吗?以前是右下移动,顺时针90°是不是就变成左下,然后180是左上这种方式?看了很久还是不太确定
回复 支持 反对

使用道具 举报

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

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