【PySide6】QChart笔记(一)—— 用QDateTimeAxis作为x轴绘制多条折线图
一、QDateTimeAxis简介
1. 官方描述
https://doc.qt.io/qtforpython-6/PySide6/QtCharts/QDateTimeAxis.html
QDateTimeAxis可以用作带有刻度线、网格线以及阴影的轴。可以通过设置适当的日期时间格式来配置标签。QDateTimeAxis有效的时间范围为4714 BCE(公元前4714)到287396 CE(公元287396)。对于其他有关于QDateTime的限制,请参考QDateTime的官方文档。
1.1 属性
| 属性 | 描述 |
|---|---|
| format | 从QDateTime对象创建轴标签时使用的字符串 |
| max | 轴的最大值 |
| min | 轴的最小值 |
| tickCount | 轴的刻度线数量 |
1.2 信号
| 信号 | 描述 |
|---|---|
| formatChanged | 属性format值改变时触发 |
| maxChanged | 属性max值改变时触发 |
| minChanged | 属性min值改变时触发 |
| rangeChanged | 属性max、min值改变时触发 |
| tickCountChanged | 属性tickCount值改变时触发 |
1.3 使用方法
QDateTimeAxis可以与所有QXYSeries(QScatterSeries, QLineSeries, QSplineSeries)搭配使用。使用时,通过调用toMSecsSinceEpoch()方法向series中加点。
2. 官方用例
https://doc.qt.io/qtforpython-6/overviews/qtcharts-datetimeaxis-example.html
【官方警告】本节包含从C++自动转换为Python的片段,其中可能包含错误
【译注:事实上示例代码确实有问题 】。
2.1 创建折线图
为了创建折线图,我们需要使用QLineSeries对象:
series = QLineSeries()
在图表中,我们将展示太阳黑子的数量随时间变化的情况,该数据从文本文件中读入。数据来源于Space Weather Prediction Center。
在下面的代码片段中,请注意如何使用toMSecsSinceEpoch()方法将QDateTime对象转换为可以传递给QLineSeries.append()方法的数字类型【译注:相当于整数型或浮点型时间戳】。
# 获取数据,存入series
# data from http://www.swpc.noaa.gov/ftpdir/weekly/RecentIndices.txt
# http://www.swpc.noaa.gov/ftpdir/weekly/README
# http://www.weather.gov/disclaimer
sunSpots = QFile(":sun_spots")
if not sunSpots.open(QIODevice.ReadOnly | QIODevice.Text):
m_loadError = "Failed to load '%1' file.".arg(sunSpots.fileName())
return False
stream = QTextStream(sunSpots)
while not stream.atEnd():
line = stream.readLine()
if line.startsWith("#") or line.startsWith(":"):
continue
values = line.split(' ', Qt.SkipEmptyParts)
momentInTime = QDateTime()
momentInTime.setDate(QDate(values[0].toInt(), values[1].toInt() , 15))
# 下面这句为官方给出的语句,会报错 OverflowError: Python int too large to convert to C long
# 请参考 “三、问题与总结” 中的内容
# series.append(momentInTime.toMSecsSinceEpoch(), values[2].toDouble())
# 解决方式如下
series.append(numpy.int64(momentInTime.toMSecsSinceEpoch()), values[2].toDouble())
sunSpots.close()
为了在图表上显示数据,我们需要QChart实例。我们向其中添加series,隐藏图例(legend),创建默认轴,并设置图表的标题。
chart = QChart()
chart.addSeries(series)
chart.legend().hide()
chart.setTitle("Sunspots count (by Space Weather Prediction Center)")
由于我们使用的是QLineSeries对象,调用createDefaultAxes()方法将创建QValueAxis对象作为X轴和Y轴。要使用QDateTimeAxis,我们需要将它手动设置到图表中【意思是,不能图省事,直接调用 createDefaultAxes() 方法了。其中 createDefaultAxes() 方法会根据 QChart 对象已绑定的 QAbstractSeries 类型自动重新创建合适的坐标轴】。
首先,创建QDateTimeAxis的实例,然后设置要显示的刻度数。太阳黑子数量的含义是某月的平均值,因此,轴标签中无需包含时间(time)和日号(day)的信息,可以通过设置自定义标签格式来实现只展示年月。
更多自定义标签格式请参考QDateTime.toString()方法文档来了解可用的格式选项。
【译注:以下代码中,MMM表示缩写的本地化月份名称(e.g. 'Jan' to 'Dec')。可在 QDateTime.toString() 方法文档中查阅】
axisX = QDateTimeAxis()
axisX.setTickCount(10)
axisX.setFormat("MMM yyyy")
axisX.setTitleText("Date")
chart.addAxis(axisX, Qt.AlignBottom)
series.attachAxis(axisX)
axisY = QValueAxis()
axisY.setLabelFormat("%i")
axisY.setTitleText("Sunspots count")
chart.addAxis(axisY, Qt.AlignLeft)
series.attachAxis(axisY)
然后我们创建一个QChartView对象,将chart作为参数。这样我们就不需要自己创建QGraphicsView场景了。我们还设置了抗锯齿功能,让渲染后的线条看起来更漂亮。
createDefaultChartView(chart)
现在可以展示图表了。
二、实践
1. 用例说明
在同一个QChart中显示两条折线,其中x轴为QDateTimeAxis类型。

2. 代码实现
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QDateTimeAxis, QValueAxis
from PySide6.QtGui import QPainter
from PySide6.QtCore import Qt, QDateTime
from PySide6.QtWidgets import QApplication, QMainWindow
import numpy as np
app = QApplication([])
window = QMainWindow()
chart = QChart()
chart.setTitle("Two Lines Chart")
# 准备数据
axisX_date = [QDateTime.currentDateTime().addDays(i) for i in range(5)]
axisY_value1 = [10 - 2 * i for i in range(5)]
axisY_value2 = [5 + i * (-1) ** i for i in range(5)]
series1 = QLineSeries()
for i in range(5):
series1.append(np.int64(axisX_date[i].toMSecsSinceEpoch()), axisY_value1[i])
series2 = QLineSeries()
for i in range(5):
series2.append(np.int64(axisX_date[i].toMSecsSinceEpoch()), axisY_value2[i])
# 将series添加到chart中
chart.addSeries(series1)
chart.addSeries(series2)
# 创建x轴
axisX = QDateTimeAxis()
axisX.setFormat("yyyy/MM/dd")
axisX.setTitleText("Date")
axisX.setTickCount(5)
axisX.setRange(QDateTime.currentDateTime(), QDateTime.currentDateTime().addDays(4))
# 将x轴与chart和series绑定
chart.addAxis(axisX, Qt.AlignBottom)
series1.attachAxis(axisX)
series2.attachAxis(axisX)
# 创建y轴
axisY = QValueAxis()
axisY.setTitleText("Value")
axisY.setRange(0, 10) # Set the range of the Y axis to 0-10
# 将y轴与chart和series绑定
chart.addAxis(axisY, Qt.AlignLeft)
series1.attachAxis(axisY)
series2.attachAxis(axisY)
# 显示图表
chartView = QChartView(chart)
chartView.setRenderHint(QPainter.Antialiasing)
window.setCentralWidget(chartView)
window.show()
app.exec()
三、问题与总结
1. OverflowError: Python int too large to convert to C long
问题描述
根据官方文档的指引,将QDateTime对象加入QChart图表的series时,需要用toMSecsSinceEpoch()方法转换为数值型,C++中完全没有问题,但在Python中却会出现该错误。
解决方法
通过numpy.int64()将调用toMSecsSinceEpoch()后过大的值转换为numpy的Int64类型,然后再传给QLineSeries.append()方法即可。即调用:
numpy.int64(QDateTime().toMSecsSinceEpoch())
2. 更新series后,图像或坐标轴缺失
问题描述
修改series中的点集后,重新绘制QChart时,出现仅显示折线而不显示坐标轴、或仅显示坐标轴而不显示折线图的情况。
解决方法
其原因是,绘制图像时,各对象的创建、绑定顺序不正确,同时坐标轴也需要重新创建。应当遵循如下顺序:
- 清除 QXYseries 对象中的旧数据,即调用
QXYseries.clear() - 将数据写入 QXYseries 对象, 即调用
QXYseries.append() - 【仅需一次】将 QXYseries 对象与 QChart 对象绑定,即调用
QChart.addSeries() - 删除旧坐标轴 QAbstractAxis 对象,并重新创建
- 将新 QAbstractAxis 对象与 QChart 对象绑定,即调用
QChart.addAxis() - 将新 QAbstractAxis 对象与 QXYseries 对象绑定,即调用
QXYseries.attachAxis()
对于一般的坐标轴类型,可直接调用 QChart.createDefaultAxes() 方法,相当于直接完成了后面三步。而对于 QDateTimeAxis 类型的坐标轴,需要自行实现类似的方法。一个例子:
def createDateTimeAxis(self, x_range, y_range):
"""
Describe: 更新series后需要重新创建坐标轴标轴,这样才能展示出新的series;
又因为x轴类型为QDateTimeAxis,无法直接调用QChart.createDefaultAxes()方法创建坐标轴,
因此需要自行实现该方法
Args:
x_range: tuple[QDateTime]
x轴范围
y_range: tuple[float]
y轴范围
"""
# 先删除旧坐标轴
self.removeAxis(self._axisX)
self.removeAxis(self._axisY)
# 创建x轴
self._axisX = QDateTimeAxis()
self._axisX.setRange(x_range[0], x_range[1])
self._axisX.setFormat("yyyy/MM")
# 创建y轴
self._axisY = QValueAxis()
self._axisY.setRange(y_range[0], y_range[1])
# 将新坐标轴与QChart和series绑定
self.addAxis(self._axisX, Qt.AlignBottom)
self.addAxis(self._axisY, Qt.AlignLeft)
for series in self.list_series_line:
series.attachAxis(self._axisX)
series.attachAxis(self._axisY)
3. 同一QChart显示多条折线时,其中一条显示不完全
问题描述
同一QChart显示多条折线时,y轴的范围限定在第一条折线series点集的数值范围中,导致另一条显示不完全。
解决方法
每次更新series后,在自定义的createDateTimeAxis()方法中,通过形参y_range,传入合适的范围。
【PySide6】QChart笔记(一)—— 用QDateTimeAxis作为x轴绘制多条折线图的更多相关文章
- Qwt开发笔记(二):Qwt基础框架介绍、折线图介绍、折线图Demo以及代码详解
前言 QWT开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,本系列旨在系统解说并 ...
- OpenGL ES学习笔记(一)——基本用法、绘制流程与着色器编译
首先声明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. 在Android.iOS等移动平台上 ...
- MySQL 笔记整理(2) --日志系统,一条SQL查询语句如何执行
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 2) --日志系统,一条SQL查询语句如何执行 MySQL可以恢复到半个月内任意一秒的状态,它的实现和日志系统有关.上一篇中记录了一 ...
- MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...
- R笔记4:ggplot绘制商务图表--玫瑰图
我们说Excel有难度的图表,可以考虑ggplot2是否更方便,本帖的例子就是用ggplot做玫瑰图. Excel做玫瑰图有一定难度,可以使用雷达图或圆环图来构建,我的博客上曾有多个帖子讨论这个,见 ...
- matlab学习笔记8 基本绘图命令-特殊图形绘制
一起来学matlab-matlab学习笔记8 基本绘图命令_3 特殊图形绘制 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等 ...
- 【代码笔记】iOS-页面调的时候隐藏工具条
代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. se ...
- python-opencv笔记 图像的读取和简单几何图形绘制
- hellocharts折线图与柱状图的上下结合酷炫效果(学习笔记)
二话不说先贴图 贴代码: LineColumnDependencyActivity.java package com.shaoxin.mylinecolumndependencyactivity; i ...
- AngularJS in Action读书笔记5(实战篇)——在directive中引入D3饼状图显示
前言: "宁肯像种子一样等待 也不愿像疲惫的陀螺 旋转得那样勉强" 这是前几天在查资料无意间看到的一位园友的签名,看完后又读了两遍,觉得很有味道.后来一寻根究底才知这是出资大诗 ...
随机推荐
- Blazor前后端框架Known-V1.2.5
V1.2.5 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. Gitee: https://gitee.com/known/Known Gith ...
- React组件设计之性能优化篇
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:空山 前言 由于笔者最近在开发中遇到了一个重复渲染导致子组 ...
- FreeBSD 内核模块和硬盘相关
查看已加载的内核模块 使用命令:kldstat 加载驱动: kldload xx 查看识别到的硬盘 使用命令:dmesg | grep sector freeBSD 查看硬件信息 使用命令:dmesg ...
- 【技术实战】Vue技术实战【四】
需求实战一 效果展示 代码展示 <template> <ARow> <ACol> <a-statistic-countdown :value="de ...
- 来会会babel这个重要且神奇的工具
babel 在前端工程化开发中发挥着至关重要的作用,它能将较高级的语法转成浏览器可识别的代码,无论中 es6 中 const .promise 还是 React.TypeScript. 以下babel ...
- [FlareOn4]login-buu ctf
打开压缩包 是个html,我直接???? 这不是web弄的吗 离谱了,不过f12还是会的 不过其中的逻辑还是比较清楚的 先用伪代码确定加密逻辑,再直接写直接进行爆破解码 wo cao,wrong!fl ...
- 《SQL与数据库基础》07. 约束
目录 约束 常见约束案例 外键约束 删除/更新行为 本文以 MySQL 为例 约束 概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据. 目的:保证数据库中数据的正确性.有效性和完整性. 分 ...
- CodeForces 1367F2 Flying Sort (Hard Version)
题意 给一个长度为\(n\)的数组,你可以有两种操作 将某一个数放置在数组开头 将某一个数放置在数组结尾 问最小操作多少次可以得到一个非递减数列 (比\(F1\)难在\(n\)变大,且数组中元素可以有 ...
- 面霸的自我修养:ThreadLocal专题
王有志,一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群:共同富裕的Java人 今天是<面霸的自我修养>第5篇文章,我们一起来看看面试中会问到哪些关于ThreadLocal ...
- 如何在.NET电子表格应用程序中创建流程图
前言 流程图是一种常用的图形化工具,用于展示过程中事件.决策和操作的顺序和关系.它通过使用不同形状的图标和箭头线条,将任务和步骤按照特定的顺序连接起来,以便清晰地表示一个过程的执行流程. 在企业环境中 ...