- 浏览: 230657 次
- 性别:
- 来自: 天朝帝都
文章分类
最新评论
-
hanmiao:
CSDN 博客地址是这個?http://blog.csdn.n ...
将博客搬至CSDN -
chenwq:
下载了,谢谢分享!
R语言学习入门 -
bbsunchen:
今天跟英姐聊天,她verbal考了151,不够啊,数学也不高。 ...
跟我一起考GRE(三) -
bbsunchen:
qinger说得对我今年只做三件事情:考好GRE,考好TOEF ...
IT行业成功必备的素质 -
bbsunchen:
还有8天就考试了,哥还在过单词啊
跟我一起考GRE(三)
这篇文章中,给出Qt坐标系统的详细介绍,在附件中,给出使用Qt制作的绘图程序,类似于windows中的画图程序。
整合了网络中可见的所有Qt绘图资源
一、坐标系简介。
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);
}
效果如下。
利用好这两个函数,可以实现快速的坐标系切换,绘制出不同的图形。
_____________________________________________________________________________
为了更清楚地获得坐标信息,我们这里利用鼠标事件,让鼠标点击左键时输出该点的坐标信息。
1.在工程中的dialog.h文件中添加代码。
添加头文件: #include <QMouseEvent>
在public中添加函数声明:void mousePressEvent(QMouseEvent *);
然后到dialog.cpp文件中:
添加头文件: #include <QDebug>
定义函数:
void Dialog::mousePressEvent(QMouseEvent *event)
{
qDebug() << event->pos();
}
这里应用了qDebug()函数,利用该函数可以在程序运行时将程序中的一些信息输出,在Qt Creator中会将信息输出到其下面的Application Output窗口。这个函数很有用,在进行简单的程序调试时,都是利用该函数进行的。我们这里利用它将鼠标指针的坐标值输出出来。
2.然后更改重绘事件函数。
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawRect(0,0,50,50);
}
我们绘制了一个左上顶点为(0,0),宽和高都是50的矩形。
3.这时运行程序。并在绘制的矩形左上顶点点击一下鼠标左键。效果如下。(点击可看大图)
因为鼠标点的不够准确,所以输出的是(1,0),我们可以认为左上角就是原点(0,0)点。你可以再点击一下矩形的右下角,它的坐标应该是(50,50)。这个方法掌握了以后,我们就开始研究这些坐标了。
研究放大后的坐标
1.我们现在进行放大操作,然后查看其坐标的变化。
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.scale(2,2); //横纵坐标都扩大2倍
painter.drawRect(0,0,50,50);
}
我们将横纵坐标都扩大2倍,然后运行程序,查看效果:
我们点击矩形右下顶点,是(100,100),比以前的(50,50)扩大了2倍。
研究QPixmap或QImage的坐标
对于QWidget,QPixmap或QImage等都是绘图设备,我们都可以在其上利用QPainter进行绘图。现在我们研究一下QPixmap的坐标(QImage与其效果相同)。
1.我们更改重绘事件函数如下。
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix(200,200);
pix.fill(Qt::red); //背景填充为红色
painter.drawPixmap(0,0,pix);
}
这里新建了一个宽、高都是200像素的QPixmap类对象,并将其背景颜色设置为红色,然后从窗口的原点(0,0)点添加该QPixmap类对象。为了表述方便,在下面我们将这个QPixmap类对象pix称为画布。
我们运行程序,并在画布的左上角和右下角分别点击一下,效果如下:
可以看到其左上角为(0,0)点,右下角为(200,200)点,是没有问题的。
2.我们再将函数更改如下。
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix(200,200);
pix.fill(Qt::red); //背景填充为红色
painter.drawPixmap(100,100,pix);
}
这时我们从窗口的(100,100)点添加该画布,那么此时我们再点击画布的右上角,其坐标会是多少呢?
可以看到,它是(100,100),没错,这是窗口上的坐标,那么这是不是画布上的坐标呢?
3.我们接着更改函数。
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix(200,200);
pix.fill(Qt::red); //背景填充为红色
QPainter pp(&pix); //新建QPainter类对象,在pix上进行绘图
pp.drawLine(0,0,50,50); //在pix上的(0,0)点和(50,50)点之间绘制直线
painter.drawPixmap(100,100,pix);
}
这里我们又新建了一个QPainter类对象pp,其中pp(&pix)表明,pp所进行的绘图都是在画布pix上进行的。
现在先说明一下:
QPainter painter(this) ,this就表明了是在窗口上进行绘图,所以利用painter进行的绘图都是在窗口上的,painter进行的坐标变化,是变化的窗口的坐标系;而利用pp进行的绘图都是在画布上进行的,如果它进行坐标变化,就是变化的画布的坐标系。
我们在画布上的(0,0)点和(50,50)点之间绘制了一条直线。这时运行程序,点击这条直线的两端,看看其坐标值。
结果是直线的两端的坐标分别是(100,100),(150,150)。我们从中可以得出这样的结论:
第一,QWidget和QPixmap各有一套坐标系统,它们互不影响。可以看到,无论画布在窗口的什么位置,它的坐标原点依然在左上角,为(0,0)点,没有变。
第二,我们所得到的鼠标指针的坐标值是窗口提供的,不是画布的坐标。
下面我们继续研究:
4.比较下面两个例子。
例子一:
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix(200,200);
qDebug() << pix.size(); //放大前输出pix的大小
pix.fill(Qt::red);
QPainter pp(&pix);
pp.scale(2,2); //pix的坐标扩大2倍
pp.drawLine(0,0,50,50); //在pix上的(0,0)点和(50,50)点之间绘制直线
qDebug() << pix.size(); //放大后输出pix的大小
painter.drawPixmap(0,0,pix);
}
例子二:
void Dialog::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix(200,200);
qDebug() << pix.size(); //放大前输出pix的大小
painter.scale(2,2); //窗口坐标扩大2倍
pix.fill(Qt::red);
QPainter pp(&pix);
pp.drawLine(0,0,50,50); //在pix上的(0,0)点和(50,50)点之间绘制直线
qDebug() << pix.size(); //放大后输出pix的大小
painter.drawPixmap(0,0,pix);
}
两个例子中都使直线的长度扩大了两倍,但是第一个例子是扩大的画布的坐标系,第二个例子是扩大的窗口的坐标系,你可以看一下它们的效果。
你仔细看一下输出,两个例子中画布的大小都没有变。
如果你看过了我写的那个绘图软件的教程(链接过去),现在你就能明白我在其中讲“问题一”时说的意思了:虽然画布看起来是大了,但是其大小并没有变,其中坐标也没有变。变的是像素的大小或者说像素间的距离。
但是,有一点你一定要搞明白,这只是在QPixmap与QWidget结合时才出现的,是相对的说法。其实利用scale()函数是会让坐标变化的,我们在开始的例子已经证明了。
结论:
现在是不是已经很乱了,一会儿是窗口,一会儿是画布,一会儿坐标变化,一会儿又不变了,到底是怎么样呢?
其实只需记住一句话:
所有的绘图设备都有自己的坐标系统,它们互不影响。
<!-- end .entry -->
- Qt绘图软件设计教程.pdf (3.6 MB)
- 下载次数: 31
发表评论
-
USACO Mother's Milk(milk3)题解
2014-12-05 11:31 1020每种状态下,只有六种移动的情况:A->B, A-> ... -
USACO Ski Course Design(skidesign) 题解
2014-11-27 00:44 2315这一题被我想复杂了,我自己加了一个约束条件,可是题目中并没有 ... -
USACO Wormholes(wormhole) 题解
2014-11-25 05:13 2085这里再次强烈推荐USACO,因为他们每一题的题解现在有视频了 ... -
USACO Combination Lock (combo)题解
2014-11-05 23:41 1045有人说这一题暴力搜索,O(N^3),naive,哥只要O( ... -
用标准库或者boost分割C++字符串
2014-09-30 04:41 1174使用标准库 #include <iostream& ... -
Qt 使用Dom 操作XML的范例
2013-05-09 13:41 1841//--------------------读------- ... -
USACO Prime Cryptarithm 题解
2013-05-08 15:53 1459此题很水,暴力搜索,然后根据条件判断,continue掉一些 ... -
USACO Calf Flac题解
2013-05-06 17:21 1130这一题有点烦 我一开始的思路是,回文序列么,就是正序字符串 ... -
USACO Barn Repair 题解
2013-04-26 19:22 1278题目翻译还是看USACO吧, 这题贪心,贪心都是很水的,还 ... -
USACO Mixing Milk 题解
2013-04-26 11:05 1405题目大意: 描述 由于乳制品产业利润很低, ... -
稍微说说动态规划和贪心
2013-04-25 10:16 944最近在做USACO的training,又碰到了gre ... -
USACO Dual Palindromes 题解
2013-04-23 14:41 1071一天水了两题,呵呵,题目确实挺水的 做完上一题,这一题已经 ... -
USACO Palindromic Squares 源码
2013-04-23 14:02 918这题很容易的,依然是暴力搜索,好吧,这一章都叫complet ... -
USACO Name That Number源码
2013-04-08 15:26 935这次一直没过的是,C++的char转int, 要用这一句 ... -
USACO Transformation源码
2013-04-03 20:59 716/* ID: bbsunch2 PROG: trans ... -
USACO MilkingCow源码
2013-04-03 20:57 840/* ID: bbsunch2 PROG: milk2 ... -
PyDev,在Eclipse中运行python
2012-04-20 10:38 2387最近学python做高精度运算。 虽然网上有很多高精度运算的 ... -
开源,选择Google Code还是Sourceforge?
2012-01-04 11:35 6254从第一个项目canto ... -
QT中文字的绘制
2011-12-06 16:11 3149为什么要做这次文字的介绍,因为在一般的教材中,还真没有文字的描 ... -
QT程序在各个平台下发布
2011-12-02 14:49 1006首先给出官方文档中,关于各个平台发布程序的连接,英文版 ht ...
相关推荐
总结一下,Qt的2D绘图涉及的关键概念有:坐标系统、`QPainter`类、图形变换、`QGraphicsView`和`QGraphicsScene`,以及`QPainterPath`。理解这些概念并熟练运用,可以帮你创建出丰富多样的2D图形界面。在实际编程...
在Qt中,2D绘图是通过QPainter类及其相关的图形对象来实现的,这是一个强大的工具,可以绘制复杂的图形、文本、图像等。本文将深入探讨Qt 2D绘图的基础知识,帮助你掌握其核心概念和技术。 首先,QPainter是Qt绘图...
在Qt框架中,2D绘图是一个强大的特性,允许开发者创建复杂的用户界面和自定义图形元素。本资源“【Qt】2D绘图之绘制简单的图形.rar”显然着重于介绍如何利用Qt进行基本的2D图形绘制。我们将深入探讨Qt中的绘图API,...
本文档将深入探讨Qt 2D绘图的基本概念和技术,包括画笔、画刷、坐标系统、文字渲染、路径绘制和图像处理。 **一、画笔(QPen)** 画笔在Qt绘图中用于定义线条的颜色、宽度、样式和结束样式等。你可以通过QPen类来...
Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动和嵌入式系统,提供了丰富的图形用户界面(GUI)功能,包括2D绘图。 首先,Qt的QPainter类是2D绘图的核心,它提供了基本的绘画操作,如绘制线条、曲线、...
这个主题涉及到如何使用Qt的图形视图框架(Graphics View Framework)来创建自定义的2D图形,包括绘制X轴和Y轴,以及在这些坐标系上展示实时(RT)数据。 首先,Qt提供了一个名为`QGraphicsView`的类,它是实现...
通过这个实验,学生将能够熟练掌握Qt的2D绘图技巧,不仅理解坐标系统的基本原理,还能灵活运用坐标变换函数,实现动态图形的创建。这些知识对于开发复杂的用户界面和游戏等应用具有极大的价值。
对于任何涉及图形显示的应用而言,理解和掌握其坐标系统是至关重要的。 #### 坐标机制 Qt的坐标系统主要用于2D绘图场景,其原点(0,0)位于左上角,x轴向右延伸,y轴向下延伸。这种布局遵循了传统的计算机图形学...
在Qt框架中,2D绘图是一个非常关键的特性,尤其在开发图形用户界面(GUI)应用程序时。窗口-视口转换是实现高效且精确2D图形绘制的核心技术。本资料包“【Qt】2D绘图之窗口-视口转换.rar”似乎包含了关于这个主题的...
1. **Qt Graphics View Framework**:这是Qt中的一个强大的图形渲染系统,用于处理复杂的2D图形和用户交互。Graphics View提供了一个可缩放的视图,可以轻松地添加、移动和修改图形项。在这个项目中,我们利用...
在Qt C++编程环境中,圆弧的绘制是图形用户界面(GUI)开发中常见的需求,尤其是在设计复杂的2D图形或游戏场景时。本教程将详细讲解如何使用Qt库中的QPainter类来基于圆心坐标、起始坐标和终点坐标绘制圆弧。 首先...
Qt的2D绘图系统基于OpenGL,支持高效且灵活的图形渲染。以下是对"Qt基本图形的绘制"这一主题的详细解释: 1. **QPainter对象**:Qt绘图的核心是`QPainter`类,它提供了一组丰富的函数,允许开发者在各种图形上下文...
首先,我们需要了解QT中的主要组件,特别是与图形绘制相关的类。在QT中,`QPainter`类是用于2D图形绘制的核心,它提供了各种绘图操作,如线条、曲线、文本和图像等。为了在窗口上绘制坐标轴,我们还需要`QWidget`或`...
Qt图形视图框架是一种高度灵活且功能强大的图形处理系统,广泛应用于各种类型的图形界面应用程序中,包括但不限于绘图软件、地图展示软件等。该框架的核心组件包括场景(Scene)、视图(View)以及图元(Item)。通过这些...
3. **坐标系统与变换**:理解QT的坐标系统,以及如何进行坐标平移、缩放、旋转等变换操作,以便灵活控制图形的显示位置和形状。 4. **文本与图像绘制**:学习如何在画布上添加文本和绘制图像,这对于创建用户界面...
《基于C++与Qt实现底层绘图算法的绘图系统详解》 在计算机科学领域,图形用户界面(GUI)的开发是一项重要的技能,而Qt库则是一个强大的跨平台开发工具,广泛应用于桌面应用、移动应用及嵌入式系统的开发。本项目...
《基于QT和QWT的2D绘图程序详解》 在计算机图形学领域,2D绘图是基础且广泛的应用之一。本篇文章将深入探讨如何使用QT框架结合QWT库来构建一个2D绘图程序。QT是一个跨平台的C++开发框架,广泛应用于桌面应用、移动...
在Qt框架中,2D绘图是一个强大的特性,它允许开发者在窗口或画布上创建丰富的图形、图像和文本。本教程重点讲解如何利用Qt进行2D绘图,特别是关于绘制文字的部分。Qt的绘图功能主要通过QPainter类来实现,这个类提供...
在`widget.cpp`和`widget.h`中,我们将定义一个继承自QWidget的类,该类包含QCustomPlot实例并处理与图形相关的逻辑。在`widget.cpp`的构造函数中,我们通常会初始化QCustomPlot对象,设置其布局,并注册鼠标移动...
在Qt库中,2D绘图是一个强大的特性,它允许开发者在窗口或画布上创建丰富的图形用户界面。本教程将深入探讨如何使用Qt进行2D图像绘制,特别是关于“绘制图片”的操作。Qt的QPainter类是实现2D绘图的核心工具,它提供...