直接用 QPainter 性能更优,尤其高频行情;QGraphicsView 适合低频交互场景;需自建 K 线聚合器、双缓冲绘图、跨线程信号通信及动态 Y 轴缩放。

Qt 里画实时 K 线图用 QGraphicsView 还是 QPainter 直接绘图?
直接用 QPainter 在 QWidget::paintEvent 或 QQuickPaintedItem 里画,性能更可控、响应更快——尤其当每秒要刷 10+ 帧(比如 Level2 行情)时,QGraphicsView 的场景树开销和 item 创建/销毁成本会明显拖慢。但如果你需要频繁缩放、拖拽、点击选中某根 K 线做弹窗分析,QGraphicsView 的坐标映射和事件分发确实省事些。
实操建议:
- 行情频率 ≤ 1 帧/秒 → 用
QGraphicsView+ 自定义QGraphicsItem,开发快,维护直观 - 行情频率 ≥ 5 帧/秒 或需 sub-ms 绘制延迟 → 放弃 scene/item,改用双缓冲
QPixmap+QPainter直接画到 widget 上,自己管理坐标缩放和平移 - 别在
paintEvent里做数据计算(比如 MA 计算)、别 new 对象、别调用网络或磁盘 IO
怎么把 tick 数据实时转成 1 分钟 K 线并更新图表?
Qt 本身不提供 K 线合成逻辑,得自己写一个轻量级的 KLineAggregator 类,用 QTimer::singleShot(0, ...) 或 QMetaObject::invokeMethod(..., Qt::QueuedConnection) 把 tick 推进聚合器,避免阻塞主线程。
关键点:
- 用
QTime截断当前 tick 时间到分钟边界(如time.startOfDay().addSecs((time.second() / 60) * 60)),作为该 K 线的datetime键 - 每个 K 线用结构体存
open、high、low、close、volume,首次 tick 设 open=close=price,后续只更新 high/low/close - 新分钟开始时,把上一根 K 线 emit 出去(信号
klineReady(const KLine&)),UI 层 connect 后调用update()或 push 到绘制缓存队列 - 别用
std::map<QDateTime, KLine>存历史 K 线——查找慢;改用QVector<KLine>+ 二分查找索引,或者直接按时间顺序 append,靠下标算偏移
鼠标滚轮缩放 K 线图时,怎么让价格轴同步缩放且不跳变?
常见错误是只缩放 X 轴(时间范围),Y 轴仍用全量数据的 min/max,导致价格刻度突然拉宽或挤扁。正确做法是:每次缩放后,根据当前可见时间范围,重新计算该窗口内所有 K 线的 high/low 极值,再设 Y 轴范围。
实操注意:
- 别在
wheelEvent里现场遍历全部 K 线算极值——卡顿;提前建好QVector<qreal>存每个 K 线的high和low,用std::minmax_element查子区间 - 缩放中心点要用
mapToScene(e->position())换算成逻辑坐标,再反推时间戳和价格值,否则滚轮中心会“漂移” - 加个最小缩放限制(比如最少显示 5 根 K 线),防止无限放大后只剩一根柱子还拼命重绘
- 用
QTransform做视图变换比手动算像素坐标更稳,但记得调用setTransform()后触发update(),而不是重绘整个 widget
连接券商 API 后,Qt 程序偶尔崩溃,大概率是什么问题?
90% 是跨线程调用 UI 对象,比如在非 GUI 线程(如 QThread 或第三方 SDK 回调线程)里直接调用了 widget->update()、label->setText(),或访问了 QPainter 对象。
必须遵守:
- 所有 UI 更新必须走 signal/slot,且 slot 连接方式指定为
Qt::QueuedConnection(即使 sender 和 receiver 在同一线程) - 券商回调里收到 tick,应 emit 一个带数据的信号(如
tickReceived(const TickData&)),由 GUI 线程的 slot 接收并处理 - 别把
QWidget指针传进工作线程;如需共享数据,用QSharedDataPointer或只传const QVector<KLine>&这类只读副本 - 检查券商 SDK 是否要求回调函数必须是静态函数或 C 风格函数指针——Qt 的 member function 默认不满足,得用
static+QObject::findChild或全局 map 缓存对象指针(慎用)
真正难的不是画线,是让 1000 根 K 线在滚动时帧率稳定在 60fps,同时 tick 不丢、缩放不糊、鼠标不卡——这些细节堆起来,才是行情软件的门槛。


















