QT6 Candlestick Chart实时数据无闪烁更新方案咨询
QT6内置了非常实用的Candlestick Chart(蜡烛图)组件。
以下是使用QML向该图表添加数据的示例代码:
import QtQuick 2.0 import QtCharts 2.2 ChartView { title: "Candlestick series" width: 800 height: 600 theme: ChartView.ChartThemeLight legend.alignment: Qt.AlignBottom antialiasing: true CandlestickSeries { name: "Acme Ltd." increasingColor: "green" decreasingColor: "red" CandlestickSet { timestamp: 1435708800000; open: 6.90; high: 6.94; low: 5.99; close: 6.60 } CandlestickSet { timestamp: 1435795200000; open: 6.69; high: 6.69; low: 6.69; close: 6.69 } CandlestickSet { timestamp: 1436140800000; open: 4.85; high: 6.23; low: 4.85; close: 6.00 } CandlestickSet { timestamp: 1436227200000; open: 5.89; high: 6.15; low: 3.77; close: 5.69 } CandlestickSet { timestamp: 1436313600000; open: 4.64; high: 4.64; low: 2.54; close: 2.54 } } }
在实际业务中经常会遇到实时数据场景,最后一根蜡烛的数值会动态变化,同时还会新增新的蜡烛数据,请问这种场景下是否可以实现蜡烛数据(图表数据)的修改、新增操作不产生页面闪烁?
比如CandlestickSeries组件仅提供了add/remove信号,没有提供changed信号,这种情况该如何处理?
解答
完全可以实现无闪烁的实时更新,哪怕CandlestickSeries没有提供全局的changed信号,也有成熟的处理方案:
1. 单根蜡烛数值更新(比如实时变动的最后一根蜡烛)
CandlestickSet的open/high/low/close/timestamp本身就是可读写的动态属性,直接修改对应CandlestickSet实例的属性值即可,Qt Charts内部会自动重绘对应单根蜡烛,不会触发全量图表重绘,自然不会产生闪烁。
你可以把所有CandlestickSet实例存在一个数组里,或者给当前活跃的最后一根蜡烛设置id,更新时直接赋值即可,示例逻辑:
// 假设最后一根蜡烛的id为lastCandle function updateLastCandle(newHigh, newClose) { if (newHigh > lastCandle.high) lastCandle.high = newHigh lastCandle.close = newClose }
2. 新增蜡烛数据优化
新增蜡烛时直接调用CandlestickSeries的append()方法添加单个CandlestickSet实例即可,不要每次清空整个series再重写所有数据。append()操作只会渲染新增的蜡烛元素,已有内容不会触发重绘,不会产生闪烁。
如果需要批量新增多根蜡烛,可以先临时关闭series的更新,批量添加完成后再开启,避免中间多次触发重绘:
candlestickSeries.blockUpdates = true // 批量添加多个CandlestickSet的逻辑 candlestickSeries.blockUpdates = false
3. 额外的防闪烁优化配置
- 实时更新场景建议关闭ChartView的默认动画,设置
animationOptions: ChartView.NoAnimation,开启动画反而容易在高频更新时出现闪烁 - 如果需要滚动显示历史数据,不要频繁修改坐标轴的范围触发全量重绘,可以固定可视区间后按需偏移,同时关闭坐标轴的属性动画
关于CandlestickSeries没有changed信号的疑问:add/remove信号只针对整根蜡烛的增删事件,单根蜡烛内部属性变更的通知由CandlestickSet自身的属性变更信号负责,你不需要主动监听这类信号来触发更新,直接修改属性后Qt Charts内部会自动处理渲染逻辑,全局changed信号并非必要组件。
内容的提问来源于stack exchange,提问作者Dmitriano

