Qt5/6实战:用QPainter在Widget上画个带边框和填充色的矩形(附源码)

张开发
2026/4/21 19:53:19 15 分钟阅读

分享文章

Qt5/6实战:用QPainter在Widget上画个带边框和填充色的矩形(附源码)
Qt5/6实战用QPainter绘制带边框与填充色的矩形第一次在Qt中看到QPainter绘制出的矩形时那种代码即界面的奇妙感至今难忘。作为Qt图形系统的核心组件QPainter就像数字世界的画笔让开发者能够精确控制每个像素的呈现。本文将带你从零开始在Widget上绘制一个具有自定义边框和填充效果的矩形过程中不仅会涉及基础API调用更会分享那些官方文档没明说但实际开发中绕不开的细节。1. 环境准备与项目创建推荐使用Qt Creator作为开发环境无论是Qt5.15还是Qt6.2都能完美运行本示例。新建项目时选择Qt Widgets Application模板会自动生成主窗口类。这里有个容易踩坑的地方项目命名时避免使用特殊字符和空格否则可能遇到编译问题。在widget.h中声明重绘事件处理函数protected: void paintEvent(QPaintEvent *event) override;提示现代Qt开发中建议使用override关键字明确表示重写虚函数这能让编译器帮助检查函数签名是否正确。2. 理解Qt坐标系系统在实现绘制逻辑前必须清楚Qt的坐标系规则原点(0,0)位于Widget的内容区域左上角不包括窗口边框X轴向右为正方向Y轴向下为正方向默认单位是像素但可通过QTransform实现缩放void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); // 测试坐标系 painter.drawText(10, 20, 坐标系原点在这里); }运行这段代码文字会出现在距离窗口内边框右侧10像素、下方20像素的位置。如果发现显示位置有偏差检查是否忽略了窗口边框的宽度。3. 实现基础矩形绘制核心绘制流程分为三个关键步骤创建QPainter对象绑定到当前Widget配置绘制工具QPen控制边框样式QBrush控制填充样式执行绘制命令调用drawRect等绘图方法void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); // 配置红色虚线边框 QPen borderPen(QColor(255, 0, 0)); borderPen.setStyle(Qt::DashLine); borderPen.setWidth(3); // 配置半透明绿色填充 QBrush fillBrush(QColor(0, 255, 0, 150)); painter.setPen(borderPen); painter.setBrush(fillBrush); // 绘制矩形左上角(50,50)宽200高100 painter.drawRect(50, 50, 200, 100); }参数说明表格参数类型说明常用值示例QPen宽度int边框粗细1-5像素QPen样式Qt::PenStyle边框线型SolidLine, DashLine, DotLineQColor透明度intAlpha通道0(全透明)-255(不透明)drawRect坐标int矩形位置尺寸(x,y,width,height)4. 高级样式定制技巧4.1 使用预设样式Qt提供了多种预设颜色和样式避免手动定义RGB值// 使用系统预设 QPen pen(Qt::GlobalColor::darkBlue); pen.setStyle(Qt::DashDotLine); // 画刷填充图案 QBrush brush; brush.setColor(Qt::yellow); brush.setStyle(Qt::Dense4Pattern);4.2 抗锯齿优化绘制斜线或曲线时开启抗锯齿可获得更平滑的效果painter.setRenderHint(QPainter::Antialiasing); painter.drawRect(100, 100, 150, 150);4.3 动态效果实现结合定时器可以实现动态绘图效果。在Widget类中添加private slots: void animateRect(); private: int m_offset 0;实现动画逻辑// 构造函数中连接定时器 QTimer *timer new QTimer(this); connect(timer, QTimer::timeout, this, Widget::animateRect); timer-start(30); // 动画处理 void Widget::animateRect() { m_offset (m_offset 2) % 100; update(); // 触发重绘 } void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawRect(50 m_offset, 50, 100, 100); }5. 常见问题解决方案问题1绘制内容不显示检查是否漏掉了painter.begin(this)或使用了错误的PaintDevice确认Widget的autoFillBackground属性为false问题2性能优化建议复杂图形考虑使用QPixmap缓存绘制结果只在变化时调用update()而非连续重绘问题3高DPI屏幕适配// 获取设备像素比 qreal ratio devicePixelRatioF(); painter.scale(ratio, ratio);完整项目源码结构/ProjectRoot ├── widget.h # 头文件声明 ├── widget.cpp # 绘制实现 ├── main.cpp # 应用入口 └── CMakeLists.txt # 构建配置实际开发中我习惯将复杂的绘制逻辑拆分成多个方法比如drawBorder()和drawContent()这样既方便维护也利于性能优化。当需要绘制多个矩形时可以考虑使用QGraphicsView框架替代直接Widget绘制这在需要交互或大量图形元素的场景下性能更好。

更多文章