QPainter基础:从创建到实战
各位同学好,我是老张。今天咱们来聊聊QPainter——Qt绘图系统的核心角色。说实话,我刚开始接触Qt时,觉得绘图这事儿挺神秘的。后来做项目多了才发现,QPainter其实就是个"画师",你给它指令,它就在画布上干活。
QPainter的创建与销毁
QPainter的使用有个铁律:必须在paintEvent里创建,用完就销毁。为什么?因为绘图资源很宝贵,系统不允许你随便乱画。
核心原则:QPainter的生命周期严格绑定在paintEvent中,不要试图在其他地方创建并使用它。
来看个标准写法:
void MyWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this); // 创建,指定画布为当前窗口
// ... 绘图操作 ...
} // 析构函数自动调用,painter自动销毁
嗯,这里有个细节:QPainter painter(this)这行代码,括号里的this就是画布。可以是QWidget、QPixmap、QImage等。我个人习惯用QPixmap做双缓冲,后面会讲到。
我曾经踩过的坑:在paintEvent外部创建QPainter,结果程序直接崩溃。后来查文档才知道,QPainter只能在paintEvent里用,这是Qt的设计约束。
销毁呢?其实不用你操心。QPainter的析构函数会自动调用end(),释放资源。但如果你用new创建了指针,记得手动delete。不过说实话,我几乎不用new来创建QPainter,栈上创建最安全。
QPainter的常用设置
画师有了,接下来得给他配工具。QPainter有三件套:画笔(QPen)、画刷(QBrush)、字体(QFont)。
画笔(QPen)
画笔负责画轮廓线。你可以设置颜色、宽度、样式等。看代码:
QPainter painter(this);
QPen pen;
pen.setColor(Qt::red); // 红色
pen.setWidth(3); // 线宽3像素
pen.setStyle(Qt::DashLine); // 虚线样式
painter.setPen(pen);
painter.drawLine(10, 10, 100, 10); // 画一条红色虚线
样式有哪些?我列个表:
| 枚举值 | 效果 | 适用场景 |
|---|---|---|
| Qt::SolidLine | 实线 | 默认,最常用 |
| Qt::DashLine | 虚线 | 辅助线、标注 |
| Qt::DotLine | 点线 | 极细的辅助线 |
| Qt::DashDotLine | 点划线 | 中心线、轴线 |
我在项目中遇到过一个问题:画虚线时,如果线宽太大,虚线效果会失真。后来发现是pen.setCapStyle()没设置对,改成Qt::RoundCap就好了。
画刷(QBrush)
画刷负责填充区域。颜色、渐变、纹理都可以。举个例子:
QBrush brush;
brush.setColor(QColor(100, 200, 100)); // 浅绿色
brush.setStyle(Qt::SolidPattern); // 实心填充
painter.setBrush(brush);
painter.drawRect(20, 20, 80, 60); // 画一个填充的矩形
画刷样式也很多:
- SolidPattern:纯色填充,最常用
- Dense1Pattern ~ Dense7Pattern:不同密度的点阵
- HorPattern / VerPattern:水平/垂直线条
- CrossPattern:交叉网格
- LinearGradientPattern:线性渐变
- RadialGradientPattern:径向渐变
小技巧:如果你需要渐变填充,直接用QLinearGradient或QRadialGradient创建画刷,效果更细腻。我做过一个仪表盘项目,用径向渐变模拟金属质感,效果很棒。
字体(QFont)
绘图时经常要写文字。字体设置很简单:
QFont font;
font.setFamily("Microsoft YaHei"); // 字体
font.setPointSize(14); // 字号
font.setBold(true); // 加粗
painter.setFont(font);
painter.drawText(50, 50, "Hello Qt!"); // 绘制文字
注意:drawText的坐标是文字左下角的位置。如果你想让文字居中,可以用drawText(rect, Qt::AlignCenter, text)。
坐标系统与变换
坐标系统是绘图的基石。QPainter默认的坐标原点在左上角,x轴向右,y轴向下。但你可以通过变换来改变它。
平移(translate)
把原点挪到别处。比如你想以窗口中心为原点画图:
painter.translate(width() / 2, height() / 2); // 原点移到中心
旋转(rotate)
绕原点旋转。角度单位是度,顺时针为正:
painter.rotate(45); // 顺时针旋转45度
缩放(scale)
放大或缩小。参数是缩放因子:
painter.scale(2.0, 1.5); // x方向放大2倍,y方向放大1.5倍
保存与恢复状态
这个很重要!变换会影响后续所有绘图。所以变换前要保存状态,画完再恢复:
painter.save(); // 保存当前状态
painter.translate(100, 100);
painter.rotate(30);
// 画图...
painter.restore(); // 恢复状态
我曾经犯过的错:画一个旋转的矩形,结果后面的所有图形都跟着转了。就是因为忘了save/restore。后来养成习惯:每次变换前先save,画完立刻restore。
知识体系总览
下面这张图概括了本章的核心内容:
说白了,QPainter的使用流程就是:创建 → 设置 → 变换 → 绘图 → 销毁。每一步都有讲究,但掌握了这些基础,你就能画出大部分想要的图形了。
我的建议:刚开始学的时候,别急着搞复杂效果。先画个矩形、写行文字,感受一下坐标系统。等你熟练了,再玩渐变、变换这些高级功能。
好了,这一章就到这里。记住:多动手写代码,光看是学不会绘图的。下一章我们聊聊QPainter的绘图API,包括画线、画矩形、画椭圆这些基本操作。