一、控件展示
本期迭代依旧围绕工艺流程图可视化控件展开,在保留原有流程图基础展示、逻辑联动能力的前提下,完成了视觉效果升级与动态交互优化。
本次开发依托AI辅助设计能力,对整体画面的光影层次、立体质感、动态特效进行全方位打磨,解决了二维流程图画面扁平、视觉单调、仿真度不足的问题,提升了工艺流程图的可视化沉浸感与界面精致度。
主要创意点有:
空容器水体流动动态效果
芯片控制闪烁交互效果
仿真式工艺文字展示效果
本次功能开发核心技术栈采用C++、Qt、QPainter,基于Qt原生绘图框架完成所有自定义绘制与动态特效开发。依托QPainter的高精度2D绘图能力,自主实现图形渲染、动画帧刷新,不依赖第三方冗余插件,保证控件运行的高效性与稳定性,同时适配各类工业软件运行环境。


二、整体思路及流程
在做工业可视化、监控大屏类界面时,经常会遇到各类动态 UI 效果:容器液位动态变化、提示文字波动、硬件芯片状态闪烁。本文记录基于QPainter+ 定时器实现一组科技风动效的开发思路,整体分为背景素材、液位动画、波动文字、芯片闪烁四个模块。
1、背景图准备
界面氛围感很大程度取决于底层背景,优先使用 AI 生成一张适配项目风格的高质量背景图。
注意:背景图分辨率尽量和界面画布匹配,避免缩放模糊;后续所有自定义绘制元素都叠加在背景之上,绘制顺序遵循先绘制背景,再绘制自定义动效组件。
拿到合适背景素材后,在 paintEvent 中优先完成背景渲染,后续所有动画元素都在这张画布之上叠加绘制。

2、液位动画
界面左侧 4 个空瓶容器,需要实现液体上下升降,模拟液体注入、抽出的动态效果。
实现思路
核心依靠QTimer定时器驱动动画帧,配合封装好的绘制工具类完成容器与液体渲染:
改变液位变量数值,实现液位上升 / 下降逻辑,控制注入、抽出动画;
液体部分使用不同颜色、亮度做区分,强化光影表现,提升画面层次感;
3、文字波动动态提示
页面标语提示,想要做出随机波动的动态文字效果。
实现思路
维护一组业务提示标语集合,通过随机数逻辑切换不同阶段的提示文案;
可搭配多套颜色值,对文字做动态颜色渲染,进一步强化科技动感。
4、芯片状态闪烁效果
模拟芯片运行状态,实现芯片边框闪烁告警效果。
实现思路
依旧是定时器驱动 + QPainter绘制矩形框完成:
定时器定时切换状态标记,维护当前闪烁的颜色;
在paintEvent中绘制芯片外围矩形边框,根据状态标记切换边框颜色;
三、源码开放
本期源码开放,完整视频在某站,搜索"Q态王"
同时如果大家需要源码可去V号,同名"Q态王"找我私信,最新版就有~
客观原因,无法放链接,
放下部分源码:(求生欲~)
void rotateAndPaintRect(QPainter *painter, const QRectF &rect, int angle,bool isRound = false,int rx = 0,int ry = 0)
{
qreal cx = 0;
qreal cy = 0;
cx = rect.center().x();
cy = rect.center().y();
painter->save();
painter->translate(cx ,cy);
painter->rotate(angle);
QPointF drawOffset = rect.topLeft() - QPointF(cx,cy);
painter->drawRect(drawOffset.x(), drawOffset.y(), rect.width(), rect.height());
painter->restore();
}
void DrawText(QPainter &painter,const QRectF &rect,QString str,double angle,int size,QString fontFamily,int textAlignment)
{
QRectF rotatedRect(-rect.width()/2, -rect.height()/2, rect.width(), rect.height());
qreal cx = rect.x() + rect.width() / 2;
qreal cy = rect.y() + rect.height() / 2;
QFont font = QFont(fontFamily, size);
painter.setFont(font);
painter.save();
painter.translate(cx, cy);
painter.scale(1, -1);
painter.rotate(-angle);//旋转角度
painter.drawText(rotatedRect,textAlignment,str);
//恢复上面保存的状态
painter.restore();
}
void DrawImage(QPainter &painter, QImage &image, const QRectF &rect,double angle)
{
QRectF rotatedRect(-rect.width()/2, -rect.height()/2, rect.width(), rect.height());
painter.drawImage(rotatedRect, image);
}
//绘制流动线段
void drawFlowLine(QPainter *painter, QPolygonF points,QColor backgroundColor,
int bgLineWidth,QColor lineColor,int lineWidth,const FlowInfo &flowInfo)
{
QPen pen(backgroundColor);
pen.setJoinStyle(Qt::RoundJoin);
pen.setStyle(Qt::SolidLine);
pen.setWidth(bgLineWidth);
pen.setCapStyle(Qt::RoundCap);
painter->setPen(pen);
painter->drawPolyline(points);
QPen pen1(lineColor);
QVector<qreal> dashes;
qreal space = 2;
dashes << 3 << space << 3 << space;
pen1.setDashPattern(dashes);
pen1.setWidth(lineWidth);
pen1.setJoinStyle(Qt::RoundJoin);
pen1.setCapStyle(Qt::RoundCap);
pen1.setDashOffset(flowInfo.offset);
painter->setPen(pen1);
painter->drawPolyline(points);
}