Qt之2D绘图4——坐标系统与坐标变换

1. Qt坐标系统由QPainter控制,同时也由 QPaintDeviceQPaintEngine类控制.QPaintDevice类是绘图设备的基类,QWidget,QPixmap,QImage,QPrinter都是QPaintDevice类的子类。Qt绘图设备默认坐标原点是左上角,X轴向右增长,Y轴向下增长,默认的单位在基于像素的设备上是像素,在打印机设备上是1/72英寸(0.35毫米).QPainter的逻辑坐标与QPainterDevice的物理坐标之间的映射由QPainter的变换矩阵,视口和窗口处理。逻辑坐标和物理坐标也是一致的。QPainter也支持坐标变换(如旋转和伸缩);

2. 坐标变换。

  通常QPainer在设备的坐标系统上绘制图形,但QPainter也支持坐标变换。可以通过QPainter::scale()函数进行比例变换。使用QPainter::rotate()函数进行旋转变换。平移变换则使用QPainter::translate()函数,QPainter::shear()函数对图形进行扭曲操作,所有变换操作的变换矩阵都可以通过QPainter::wordTransform()函数取出。不同的变换矩阵可以使用堆栈保存。

QPainter::save()保存变换矩阵到堆栈,用QPainter::restore()函数将其弹出堆栈。

  QMatrix(QTransform)定义了系统的二维变换。QMatrix(QTransform)对象实际上定义了一个3x3矩阵。

  --------------

  m11  m12  0

  m21  m22  0

  dx   dy   1

  ---------------

   x\\'=m11*x+m21*y+dx;

   y\\'=m22*y+m12*x+dy;

其中dx,dy表示水平和垂直偏移量,m11,m22表示水平和垂直方向上的比例。m12m21表示水平和垂直方向上的扭曲程度。

   矩阵可以通过setMatrix函数进行设置,然后可以使用translate(),rotate(),scale(),shear()等函数进行变换.Qt4.3中引入QTransform类表示变换矩阵。与QMatrix不同的是,QTransform()支持透视变换。使用toAffine()函数可以将QTransform对象转换为QMatrix对象。这将丢失QTransform的透视变换数据。逻辑坐标和物理坐标的变换由QPainterworldMatrix()函数。以及QPainterviewport()window()函数处理。视口表示物理坐标下的任意矩形。而在窗口表示在逻辑坐标下的相同矩形。默认情况下逻辑坐标与物理坐标时相同的。与绘图设备上的矩形也是一致的。使用窗口-视口变换可以使逻辑坐标符合自定义要求,这个机制通常用来完成设备无关的绘图代码。例如,可以设置逻辑坐标(-100,-100)(100,100)且在原点(0,0),通过调用QPainter::setWindow()函数可以完成下列操作。

 QPainter painter(this);

 painter.setWindow(QRect(-100,-100,200,200));

现在,逻辑坐标的(-100,-100)对应着绘图设备的(0,0),这样可以绘制独立于设备,始终在指定逻辑坐标上工作。设置窗口或视口矩形实际上是执行线性变换。本质上是窗口四个角映射到对应的视口四个角,反之亦然,因此保持视口和窗口x轴和y轴之间的比例变换一致,保证变换没有变形。窗口-视口变换只是线性变换,不执行裁剪操作,例如当绘制超出窗口后,这些绘制仍然 通过线性变换映射到

视口进行绘制。Qt的绘制过程是进行坐标变换,在进行窗口-视口变换。

使用不同的字体

  Qt提供了Font类来表示字体,当创建QFont对象时,Qt会使用指定的字体,如果没有对应的字体,Qt将寻找一种最接近的已安装字体。字体信息可以通过
QFontInfo取出,并可用QFontMetrics取得字体的相关数据。函数exactMatch()判断底层窗口系统中是否有完全对应的字体。使 用QApplication::setFont()可以设置应用程序默认的字体,如果选择的字体不包括所有要显示的字符,QFont将会尝试寻找最基接近 的字体。当QPainter绘制指定的字体中不存在的字符时
将绘制一个空心的正方行。

绘图路径  --QPainterPath
绘图路径(painter path)由基本图元(矩形,椭圆,直线,曲线)组成,绘图路径可以是闭合的路径,如矩形和圆,或者是非闭合的路径,如直线和曲线。绘图路径在Qt中使用QPainterPth类表示,
它提供了绘图操作的容器,可以使图形能够复用。绘图路径可以进行填充,显示轮廓和裁剪。要生成可填充的轮廓的绘图路径,可以使用QPainterPathStroker.使用QPainterPath的优点是复杂的
图形只需创建一次,就可以多次使用。QPainterPath对象可以时只有起点的空路径,或者从其他QPainterPath对象复制,创建了QPainterPath对象后,可以使用lineTo(),cubicTo(),
quadTo()函数将直线和曲线添加到路径中来,直线和曲线从currentPosition()开始绘制。currentPosition()总是返 回最后的子路经绘制的终点。使用moveTo()函数可以在不增加路径的情况下移动currentPositon(),它关闭了一个子路经,开始一个新的 子路经。closeSubPath()也可以关闭当前路径,并从currentPosition()连接一条直线到绘图路径的起点。QPainter可以 使用addEllipse(),addPath(),addRect(),addRegion(),addText()Qt的一些基本图元加入绘图路 径。一个已有的绘图路径可以通过connectPath()函数加入到另一个绘图路径中。
如下代码绘制了一个箭头:
QPainterPath path;
path.moveTo(10,100);
path.cubicTo(10,100,100,10,200,70);
path.lineTo(200,50);
path.lineTo(220,80);
path.lineTo(200,110);
path.lineTo(200,90);
path.cuticTo(200,100,100,50,50,100);

QPainter painter(this);
QPen pen(QColor(255,0,0),2);
painter.setPen(pen);
painter.drawPath(path);

Qt提供了两种填充方式,Qt::OddEventFillQt::WindingFill.Qt::OddEvent时默认的填充规则,它指定 QPainterPath使用奇偶填充规则,该规则判断一个点是否在论经图形内的方法是从该店画一条水平线到路径外,计算水平线和路径的交点数,如果交点 时奇数个则说明该点在路径图形内。QPainterPath还有一些函数可以获取路径信息,如elementAt()函数可以取出指定的子路经元素,
isEmpty()函数判断当前路径是否为空。controlPointRect()函数返回路径中所有的点和控制点的矩形,该函数运行速度比返回精确包 容框boundingRect()函数快得多。contains()函数判断一个点或一个矩形是否在路径内。intersects()判断指定的矩形与路 径是否相交.QPainterPath可以将矩形图形转换为其他图形,如使用 toFillPolygon(),toFillPolygon(),toSubpathPOlygons()函数将路径转化为多边形。
QPainterPath还可以使用文字作为路径,下面的代码演示了文字路径,并使用线性渐变填充。
QLinearGradient linearGrad(QPointF(200,0),QPointF(1000,0));
linearGrad.setColorAt(0,Qt::black);
linearGrad.setColorAt(1,Qt::white);
QFont font("隶书",80);
font.setBold(true);
QPainterPath textPath();
textPath.addText(200,300,font,tr("电子工业出版社"));
painter.setBrush(linearGrad);
painter.drawPath(textPath);


转载于:https://my.oschina.net/jintao/blog/80660

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值