• 17614阅读
  • 12回复

十六、Qt 2D绘图(六)坐标系统(原创) [复制链接]

上一主题 下一主题
离线yafei86
 
只看楼主 倒序阅读 楼主  发表于: 2010-01-24
— 本帖被 XChinux 设置为精华(2011-01-06) —
声明:本文原创于yafeilinux的百度博客,http://hi.baidu.com/yafeilinux 转载请注明出处。
前面一节我们讲解了图片的显示,其中很多都用到了坐标的变化,这一节我们简单讲一下Qt的坐标系统,其实也还是主要讲上一节的那几个函数。这里我们先讲解一下Qt的坐标系,然后讲解那几个函数,它们分别是:
translate()函数,进行平移变换;scale()函数,进行比例变换;rotate()函数,进行旋转变换;shear()函数,进行扭曲变换。
最后介绍两个有用的函数save()和restore(),利用它们来保存和弹出坐标系的状态,从而实现快速利用几个变换来绘图。
一、坐标系简介。
Qt中每一个窗口都有一个坐标系,默认的,窗口左上角为坐标原点,然后水平向右依次增大,水平向左依次减小,垂直向下依次增大,垂直向上依次减小。原点即为(0,0)点,然后以像素为单位增减。
例如:
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::red);
    painter.drawRect(0,0,100,100);
    painter.setBrush(Qt::yellow);
    painter.drawRect(-50,-50,100,100);
}

我们先在原点(0,0)绘制了一个长宽都是100像素的红色矩形,又在(-50,-50)点绘制了一个同样大小的黄色矩形。可以看到,我们只能看到黄色矩形的一部分。效果如下图。

二、坐标系变换。
坐标系变换是利用变换矩阵来进行的,我们可以利用QTransform类来设置变换矩阵,因为一般我们不需要进行更改,所以这里不在涉及。下面我们只是对坐标系的平移,缩放,旋转,扭曲等应用进行介绍。
1.利用translate()函数进行平移变换。
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::yellow);
    painter.drawRect(0,0,50,50);

   painter.translate(100,100); //将点(100,100)设为原点
    painter.setBrush(Qt::red);
    painter.drawRect(0,0,50,50);

   painter.translate(-100,-100);
    painter.drawLine(0,0,20,20);
}
效果如下。


这里将(100,100)点作为了原点,所以此时(100,100)就是(0,0)点,以前的(0,0)点就是
(-100,-100)点。要想使原来的(0,0)点重新成为原点,就是将(-100,-100)设为原点。
2.利用scale()函数进行比例变换,实现缩放效果。
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::yellow);
    painter.drawRect(0,0,100,100);

    painter.scale(2,2); //放大两倍
    painter.setBrush(Qt::red);
    painter.drawRect(50,50,50,50);
}
效果如下。


可以看到,painter.scale(2,2),是将横纵坐标都扩大了两倍,现在的(50,50)点就相当于以前的
(100,100)点。
3.利用shear()函数就行扭曲变换。
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::yellow);
    painter.drawRect(0,0,50,50);

    painter.shear(0,1); //纵向扭曲变形
    painter.setBrush(Qt::red);
    painter.drawRect(50,0,50,50);
}
效果如下。


这里,painter.shear(0,1),是对纵向进行扭曲,0表示不扭曲,当将第一个0更改时就会对横行进行扭曲,关于扭曲变换到底是什么效果,你观察一下是很容易发现的。
4.利用rotate()函数进行比例变换,实现缩放效果。
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawLine(0,0,100,0);
    painter.rotate(30); //以原点为中心,顺时针旋转30度
    painter.drawLine(0,0,100,0);
   painter.translate(100,100);
    painter.rotate(30);
    painter.drawLine(0,0,100,0);
}
效果如下。

因为默认的rotate()函数是以原点为中心进行顺时针旋转的,所以我们要想使其以其他点为中心进行旋转,就要先进行原点的变换。这里的painter.translate(100,100)将(100,100)设置为新的原点,想让直线以其为中心进行旋转,可是你已经发现效果并非如此。是什么原因呢?我们添加一条语句,如下:
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawLine(0,0,100,0);
    painter.rotate(30); //以原点为中心,顺时针旋转30度
    painter.drawLine(0,0,100,0);
   painter.rotate(-30);
    painter.translate(100,100);
    painter.rotate(30);
    painter.drawLine(0,0,100,0);
}

效果如下。

这时就是我们想要的效果了。我们加的一句代码为painter.rotate(-30),这是因为前面已经将坐标旋转了30度,我们需要将其再旋转回去,才能是以前正常的坐标系统。不光这个函数如此,这里介绍的这几个函数均如此,所以很容易出错。下面我们将利用两个函数来很好的解决这个问题。
三、坐标系状态的保护。
我们可以先利用save()函数来保存坐标系现在的状态,然后进行变换操作,操作完之后,再用restore()函数将以前的坐标系状态恢复,其实就是一个入栈和出栈的操作。
例如:
void Dialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.save(); //保存坐标系状态
    painter.translate(100,100);
    painter.drawLine(0,0,50,50);
    painter.restore(); //恢复以前的坐标系状态
    painter.drawLine(0,0,50,50);
}
效果如下。


利用好这两个函数,可以实现快速的坐标系切换,绘制出不同的图形。
欢迎访问我们的网站:www.yafeilinux.com
离线qinpanke

只看该作者 1楼 发表于: 2010-01-26
QMatrix
The QMatrix class specifies 2D transformations of a coordinate system.
QQ      308367961
email  qinpanke@sina.com
Blog    http://hi.baidu.com/qinpanke/blog/category/Qt
欢迎大家访问我的博客  共同学习提高
离线wd007

只看该作者 2楼 发表于: 2010-01-26
不错,效果图没有
欢迎访问我的博客,一起学习提高
http://blog.csdn.net/qter_wd007
离线sdink87
只看该作者 3楼 发表于: 2010-01-31
飞。。。是你啊??哈哈。。
离线asun
只看该作者 4楼 发表于: 2010-02-02
多谢楼主。。
离线帅坤
只看该作者 5楼 发表于: 2010-04-08
嘿嘿,谢啦,好东西!
离线jiamengyu
只看该作者 6楼 发表于: 2010-04-18
QMatrix只不过是最基本的一些像素点的坐标变换而已,如果cpu速度低,还是自己写个算法吧
离线davis45
只看该作者 7楼 发表于: 2010-05-18
一直没搞懂shear()函数的作用。。。
谢谢大家的指教
离线lore乞丐
只看该作者 8楼 发表于: 2010-05-18
学习了,如果图文一起,效果更好
离线450196683
只看该作者 9楼 发表于: 2010-11-30
如何在同一个位置,通过点击按钮来显示不同的图片?
离线江上清风

只看该作者 10楼 发表于: 2014-03-26
有新的认识,可惜没图,有图的话会更快理解
离线篮孩子

只看该作者 11楼 发表于: 2014-03-30
学习了。。。。以后可能会用到
离线yanche

只看该作者 12楼 发表于: 2014-04-08
分析的不错,顶一个
具有十年研发经验的团队,专注于C++、Qt、Python等语言,专业软件开发团队,致力于完美解决客户的需求,我们期待与您的洽谈。
业务范畴:应用软件定制、UI定制、各类管理系统定制、仿真设计、三维开发、通信SDK定制、Logo设计等等
QQ:548725431
微信:yanche521
快速回复
限100 字节
 
上一个 下一个