HelloQt(⼗五)——QT坐标系统
⼀、QT坐标系简介
Qt中每⼀个窗⼝都有⼀个坐标系,默认窗⼝左上⾓为坐标原点,然后⽔平向右依次增⼤,⽔平向左依次减⼩,垂直向下依次增⼤,垂直向上依次减⼩。原点即为(0,0)点,以像素为单位增减。
1、物理坐标系
物理坐标系即设备坐标系,原点在左上⾓的位置,单位为像素,X坐标向右增长,Y坐标向下增长。
2、逻辑坐标系
抽象坐标系,单位由具体问题决定,坐标轴的增长⽅向由具体问题决定。
QPainter使⽤逻辑坐标系绘制图形,逻辑坐标系中图形的⼤⼩和位置会转换为物理坐标系后绘制在设备上。默认情况下,逻辑坐标系与物理坐标系相同。
3、视⼝
视⼝(view port)是物理坐标系中任意指定的矩形区域。
4、窗⼝
窗⼝是逻辑坐标系中对应到物理坐标系中的相同矩形区域。
视⼝与窗⼝是不同坐标系下的同⼀个矩形,视⼝与窗⼝中的坐标点存在⼀⼀映射的关系,视⼝和窗⼝通过坐标变换可以相互转换。
⼆、坐标系变换
QPainter逻辑坐标与QPaintDevice物理坐标的映射,由QPainter的变换矩阵(transformation matrix)、视⼝(viewport)和窗⼝(window)完成。默认情况下,物理坐标与逻辑坐标系统是重合的,QPainter也⽀持坐标转换, 例如:旋转、缩放。
坐标系变换是利⽤变换矩阵来进⾏的, 通常利⽤QTransform类来设置变换矩阵。QPainter类提供了对坐标系的平移,缩放,旋转,扭曲等变换函数。
void translate(const QPointF & offset)
void translate(const QPoint & offset)
void translate(qreal dx, qreal dy)
void scale(qreal sx, qreal sy)
void shear(qreal sh, qreal sv)
void rotate(qreal angle)
void save()
void restore()
1、平移变换
QT利⽤translate()函数进⾏平移变换。
平移变换代码:
QPainter painter(this);
painter.setBrush(Qt::yellow);
painter.drawRect(0,0,50,50);
/
/将当前坐标系下的点(100,100)设为原点
painter.setBrush(Qt::red);
painter.drawRect(0,0,50,50);
//将当前坐标系下的点(-100,-100)设为原点    anslate(-100,-100);
painter.drawLine(0,0,20,20);
2、⽐例变换
利⽤scale()函数进⾏⽐例变换,实现缩放效果。⽐例变换代码:
QPainter painter(this);
painter.setBrush(Qt::yellow);
painter.drawRect(0,0,100,100);
/
/将坐标系在x,y⽅向放⼤2倍
painter.scale(2,2);
painter.setBrush(Qt::red);
painter.drawRect(50,50,50,50);
3、扭曲变换
利⽤shear()函数就⾏扭曲变换。
扭曲变换代码:
QPainter painter(this);
painter.setBrush(Qt::yellow);
painter.drawRect(0,0,50,50);
//对当前坐标系的y轴进⾏扭曲
painter.shear(0,1);
painter.setBrush(Qt::red);
painter.drawRect(50,0,50,50);
4、翻转变换
利⽤rotate()函数进⾏翻转变换。
翻转变换代码:
QPainter painter(this);
//以原点为中⼼,顺时针旋转30度
painter.drawLine(0,0,100,0) ;
//以原点为中⼼,顺时针再旋转30度
painter.drawLine(0,0,100,0);
5、坐标系状态的保护
绘图过程中需要快速的进⾏坐标系切换,绘制出不同的图形,因此需要对坐标系状态进⾏保护,可以先利⽤save()函数来保存坐标系现在的状态,然后进⾏变换操作,操作完之后,再⽤restore()函数将以前的坐标系状态恢复,本质是对坐标系进⾏⼊栈和出栈的操作。
坐标系状态保护代码:
QPainter painter(this);
//保存当前坐标系状态
painter.save();
//平移坐标系原点到(100, 100)
painter.drawLine(0,0,50,50);
//将当前原点位于点(100, 100)的坐标系恢复到保存的坐标系状态
painter.drawLine(0,0,50,50);
三、绘图实例
1、正弦波绘制
SineWave.h⽂件:
#ifndef SINEWAVE_H
#define SINEWAVE_H
#include <QWidget>
#include <QPainter>
class SineWave : public QWidget
{
Q_OBJECT
private:
void drawBackGround(QPainter* painter);
void drawCave(QPainter* painter);
void paintEvent(QPaintEvent *event);
public:
SineWave(QWidget *parent = 0);
~SineWave();
};
#endif // SINEWAVE_H
SineWave.cpp⽂件:
#include "SineWave.h"
#include <QPen>
#include <QPointF>
#include <qmath.h>
SineWave::SineWave(QWidget *parent):QWidget(parent)
{
}
SineWave::~SineWave()
{
qt viewport}
void SineWave::drawBackGround(QPainter* painter)
{
QPen pen;
const double delta = 1;
pen.setStyle(Qt::SolidLine);
painter->setViewport(50, 50, width()-100, height()-100);
painter->setWindow(-10, 2, 20, -4); // (-10, 2)    (10, -2)
painter->fillRect(-10, 2, 20, -4, Qt::black);
pen.setColor(Qt::white);
pen.setWidthF(painter->window().width()/painter->viewport().width() * delta);
painter->setPen(pen);
painter->drawLine(QPointF(-10, 1.5), QPointF(10, 1.5));
painter->drawLine(QPointF(-10, 1), QPointF(10, 1));
painter->drawLine(QPointF(-10, 0.5), QPointF(10, 0.5));
painter->drawLine(QPointF(-10, -0.5), QPointF(10, -0.5));
painter->drawLine(QPointF(-10, -1), QPointF(10, -1));
painter->drawLine(QPointF(-10, -1.5), QPointF(10, -1.5));
pen.setWidthF(painter->window().height()/painter->viewport().height() * delta);    painter->setPen(pen);
painter->drawLine(QPointF(-8, 2), QPointF(-8, -2));
painter->drawLine(QPointF(-6, 2), QPointF(-6, -2));
painter->drawLine(QPointF(-4, 2), QPointF(-4, -2));
painter->drawLine(QPointF(-4, 2), QPointF(-4, -2));
painter->drawLine(QPointF(-2, 2), QPointF(-2, -2));
painter->drawLine(QPointF(2, 2), QPointF(2, -2));
painter->drawLine(QPointF(4, 2), QPointF(4, -2));
painter->drawLine(QPointF(6, 2), QPointF(6, -2));
painter->drawLine(QPointF(8, 2), QPointF(8, -2));
pen.setWidthF(painter->window().width()/painter->viewport().width() * delta*10);
pen.setColor(Qt::green);
painter->setPen(pen);
painter->drawLine(QPointF(-10, 0), QPointF(10, 0));  // x
pen.setWidthF(painter->window().height()/painter->viewport().height() * delta*10);
painter->setPen(pen);
painter->drawLine(QPointF(0, 2), QPointF(0, -2));  // y
}
void SineWave::SineWave::drawCave(QPainter* painter)
{
for(double x=-10; x<10; x+=0.01)
{
double y = qSin(x);
painter->drawPoint(QPointF(x, y));
}
}
void SineWave::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
drawBackGround(&painter);
drawCave(&painter);
}
2、绘图板
功能需求:可以⾃由绘制图形,直线,矩形,椭圆,并可以选择绘制线条颜⾊。
A、⾃由图形绘制
⾃由绘图必须记录⿏标移动时经过的所有点的坐标,绘图参数必须有能⼒保存所有的坐标。绘制图形⽅案如下:
a、⿏标按下开始绘图,记录开始坐标
b、记录⿏标移动时经过的点坐标
c、⿏标释放时结束绘图,记录结束坐标

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。