【Qt】绘图

绘图

Qt 提供了画图相关的 API,可以允许我们在窗口上绘制任意的图形形状,来完成更复杂的界面设计。
绘图API核心类

说明
QPainter "画家" 用来绘图的对象,提供了一系列 drawXXX 方法,可以允许我们绘制各种图形
QPaintDevice "画板" 描述了 QPainter 把图形画到哪个对象上,之前的 QWidget 也是一种 QPaintDevice
QPen "画笔" 描述了 QPainter 画出来的线是什么样的
QBrush "画刷" 描述了 QPainter 填充了一个区域是什么样的

QPainter



这里画笔的样式有以下几种:

QBrush

其中画刷的样式有以下几种:


例如使用 Qt::DiagCrossPattern

绘制图片

平移坐标轴:translate(x, y) 表示水平方向上平移 x 单位,垂直方向上平移 y 单位。窗口默认大小为800*600,所以 translate(800,600) 后,坐标原点就跑右下角了。
旋转坐标轴:rotate(angel) 表示将坐标原点旋转 angel 角度,单位是度。angel 为正数表示顺时针。

视口和窗口

视口是指绘图设备的任意一个矩形区域,它使用物理坐标系。我们可以只选取物理坐标系中的一个矩形区域来绘图,默认情况下,视口等于绘图设备的整个矩形区域。窗口与视口是同一个矩形区域,但是窗口是用逻辑坐标系定义的,窗口可以直接定义矩形区域的逻辑坐标范围。

如下图矩形区域就是代表绘图设备的物理大小和坐标范围,假设大小为300*200像素。取其中间的一个正方形区域作为视口,卡其色的正方形区域就是视口。在绘图设备的物理坐标系中,视口的左上角坐标为 (50,0), 右下角坐标为 (250,200)。

QPainter 的函数 setViewport() 用于定义视口,有两种参数形式,其函数原型定义如下:

void QPainter::setViewport(const QRect &rectangle)

void QPainter::setViewport(int x, int y, int width, int height)

其中,(x, y) 是视口左上角在物理坐标系中的坐标,width 是视口宽度, height 是视口高度。上图中的视口需使用下面的语句:

painter.setViewport(50, 0, 200, 200);

这表示从绘图设备的物理坐标系中的一个点(50, 0) 开始,取宽度 300,高度 200像素的一个区域作为视口。对于上图视口所表示的正方形区域,我们定义如上图所示的一个窗口,窗口坐标系的原点在正方形的中心,并设置正方形的逻辑边长为 100。QPainter 的函数 setWindow() 用于定义窗口,有两种参数形式,其函数原型如下:

void QPainter::setWindow(const QRect &rectangle)

void QPainter::setWindow(int x, int y, int width, int height)

其中,(x, y) 是窗口左上角的坐标,width 是窗口逻辑宽度, height 是窗口逻辑高度。上图中的窗口需使用下面的语句:

painter.setWindow(-50, -50, 100, 100);

这表示对应于视口的正方形区域,其窗口左上角的逻辑坐标是 (-50, -50),窗口宽度为 100,高度为 100.这里设置的窗口仍为一个正方形,使得从视口变换到窗口时,长和宽的比例是相同的。实际可以任意指定窗口的逻辑坐标范围,长和宽的比例不同也是可以的。

视口窗口使用实例

使用窗口坐标系的优点是:在绘图时只需按照窗口坐标系定义来绘图,而不用关注实际的物理坐标范围。例如在一个固定边长为 100 的正方形窗口内绘图,当实际绘图设备大小变化时,绘图的图形会自动相应改变大小。这样,绘图功能与绘图设备是分离的,绘图功能可适用于不同大小、不同类型的绘图设备。

取高度和宽度中较小的一边为正方形边长,且图形是自动缩放的。

代码如下:

cpp 复制代码
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    int W = width();
    int H = height();
    int side = qMin(W,H);
    QRect rect((W-side)/2,(H-side)/2,side,side);
    painter.drawRect(rect);
    painter.setViewport(rect);
    painter.setWindow(-100,-100,200,200);
    QPen pen;
    pen.setWidth(1);
    pen.setColor(Qt::red);
    pen.setStyle(Qt::SolidLine);
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::BevelJoin);
    painter.setPen(pen);

    for(int i = 0; i < 36; i++)
    {
        painter.drawEllipse(QPoint(50,0),50,50);
        painter.rotate(10);//画一个圆旋转10度
    }
}

增加渐变填充和叠加效果的设置:

代码如下:

cpp 复制代码
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    int W = width();
    int H = height();
    int side = qMin(W,H);
    QRect rect((W-side)/2,(H-side)/2,side,side);
    painter.drawRect(rect);
    painter.setViewport(rect);
    painter.setWindow(-100,-100,200,200);
    QPen pen;
    pen.setWidth(1);
    pen.setColor(Qt::red);
    pen.setStyle(Qt::SolidLine);
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::BevelJoin);
    painter.setPen(pen);

    //线性渐变
    QLinearGradient linearGrad(0,0,100,0);//从左到右
    linearGrad.setColorAt(0,Qt::yellow);//起点颜色
    linearGrad.setColorAt(1,Qt::green);//终点颜色
    linearGrad.setSpread(QGradient::PadSpread);//展布模式
    painter.setBrush(linearGrad);

    //设置组合模式
    painter.setCompositionMode(QPainter::CompositionMode_Difference);
//    painter.setCompositionMode(QPainter::RasterOp_NotSourceXorDestination);
//    painter.setCompositionMode(QPainter::CompositionMode_Exclusion);

    for(int i = 0; i < 36; i++)
    {
        painter.drawEllipse(QPoint(50,0),50,50);
        painter.rotate(10);//画一个圆旋转10度
    }
}

以上窗口视口内容及代码为王维波等老师的书籍 《Qt6 C++ 开发指南》中的内容。

相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript