pyqtgraph+pyside6实现多y轴实时更新数据

"""
本专题的绘图均采用 PySide6 QWidget + pyqtgraph PlotWidget 的方式
目的是为了将图像嵌入UI界面中,包括父子关系和信号传递的技巧分享
"""
import random
import sys
import time

from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QWidget, QVBoxLayout, QApplication
import pyqtgraph as pg


class Figure(pg.PlotWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        # 背景默认使用黑色

        # 定义y1~y4
        self.y1 = pg.AxisItem('right')
        self.y1.setLabel('y1', color='blue')
        self.y1.setPen('blue')

        self.y2 = pg.AxisItem('right')
        self.y2.setLabel('y2', color='red')
        self.y2.setPen('red')

        self.y3 = pg.AxisItem('right')
        self.y3.setLabel('y3', color='green')
        self.y3.setPen('green')

        self.y4 = pg.AxisItem('right')
        self.y4.setLabel('y4', color='yellow')
        self.y4.setPen('yellow')

        # 定义v1~v4
        self.v1 = pg.ViewBox()
        self.v2 = pg.ViewBox()
        self.v3 = pg.ViewBox()
        self.v4 = pg.ViewBox()

        # 创建布局
        lay = pg.GraphicsLayout()
        self.setCentralWidget(lay)

        # p0 作为主要视窗, vp0是它的 ViewBox
        self.p0 = pg.PlotItem()
        # p0 从界面获取主要纵坐标y0
        self.p0.getAxis('left').setLabel('y0', color='white')
        self.p0.getAxis('left').setPen('white')
        self.vp0 = self.p0.vb
        # 主视窗的变化链接到所有视窗的绑定函数
        self.vp0.sigResized.connect(self.update)

        # 从左到右排布纵坐标轴
        # 关键点在于 p0 放在第二列,p0 的纵坐标 y0 放在第一列
        lay.addItem(self.p0, row=1, col=2, rowspan=2, colspan=1)
        lay.addItem(self.p0.getAxis('left'), row=1, col=1)

        # y1~y4的位置
        lay.addItem(self.y1, row=1, col=3, rowspan=1, colspan=1)
        lay.addItem(self.y2, row=1, col=4, rowspan=1, colspan=1)
        lay.addItem(self.y3, row=1, col=5, rowspan=1, colspan=1)
        lay.addItem(self.y4, row=1, col=6, rowspan=1, colspan=1)

        # 新建一个空横轴,注意颜色一定要与画布背景颜色一致,才能隐藏该轴
        x_ept = pg.AxisItem('bottom')
        # !!!!!!! 空轴千万不能设置标签(本身隐藏也没必要),否则会导致纵坐标零点错位,本教程做无用功
        # 如下语句若启用则纵坐标零点错位,可以对比运行试试
        # x_ept.setLabel('x_emp', color='black')
        x_ept.setPen('black')
        # 空轴的列(col)可以换成其他,不妨自己尝试更改下看看效果
        lay.addItem(x_ept, row=2, col=10)

        # 这里建议用布局添加标签的方式间接给横坐标轴标签,但是得用 HTML 语言
        lay.addLabel("<p style='color:white;'>风量 [m\u00b3/h]<\p>", 3, 2)

        # 布局场景添加 v1~v4
        lay.scene().addItem(self.v1)
        lay.scene().addItem(self.v2)
        lay.scene().addItem(self.v3)
        lay.scene().addItem(self.v4)

        # 将 y1~y4 绑定到 v1~v4
        self.y1.linkToView(self.v1)
        self.y2.linkToView(self.v2)
        self.y3.linkToView(self.v3)
        self.y4.linkToView(self.v4)

        # 将 v1~v4 的横坐标关联到主要视窗 vp0
        self.v1.setXLink(self.vp0)
        self.v2.setXLink(self.vp0)
        self.v3.setXLink(self.vp0)
        self.v4.setXLink(self.vp0)

        # 绘图函数
        # self.draw()
        self.x = []
        self.y0=[]
        self.y1=[]
        self.y2=[]
        self.y3=[]
        self.y4=[]
        timer = QTimer(self)
        timer.timeout.connect(self.draw)
        timer.start(1000)

    def draw(self):
        # 偷懒就将所有曲线坐标相等了,运行程序后可以自己拖动坐标轴分开
        timestamp = time.time()
        self.x.append(timestamp)
        # y0 = y1 = y2 = y3 = y4 = x
        self.y0.append(random.randint(17, 20))
        self.y1.append(random.randint(255, 280))
        self.y2.append(random.randint(2, 10))
        self.y3.append(random.randint(100, 150))
        self.y4.append(random.randint(1112, 1500))


        self.vp0.addItem(pg.PlotCurveItem(self.x, self.y0, pen=pg.mkPen(color='white', width=2)))
        self.v1.addItem(pg.PlotCurveItem(self.x, self.y1, pen=pg.mkPen(color='blue', width=2)))
        self.v2.addItem(pg.PlotCurveItem(self.x, self.y2, pen=pg.mkPen(color='red', width=2)))
        self.v3.addItem(pg.PlotCurveItem(self.x, self.y3, pen=pg.mkPen(color='green', width=2)))
        self.v4.addItem(pg.PlotCurveItem(self.x, self.y4, pen=pg.mkPen(color='yellow', width=2)))

    def update(self):
        # 所有视窗位置绑定到主要视窗 vp0, 若无则布局错乱
        self.v1.setGeometry(self.vp0.sceneBoundingRect())
        self.v2.setGeometry(self.vp0.sceneBoundingRect())
        self.v3.setGeometry(self.vp0.sceneBoundingRect())
        self.v4.setGeometry(self.vp0.sceneBoundingRect())


# PySide6 中定义 QWidget,用于嵌入上述 PlotWidget
class WidgetWindow(QWidget):
    def __init__(self):
        super().__init__()

        # 简单设置下窗口尺寸
        self.resize(500, 500)

        # 导入PlotWidget类, 用self写作类变量是为了扩展处理数据方便
        # Figure(self)是将WidgetWindow定义为Figure的父项
        self.cuv = Figure(self)

        # 创建一个垂直布局,并将self.cuv添加进去
        layout = QVBoxLayout()
        layout.addWidget(self.cuv)
        self.setLayout(layout)

        # 至此,WidgetWindow已经嵌入了Figure, 即PlotWidget, 下面运行程序
        # **************************************************************END


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WidgetWindow()
    win.show()
    sys.exit(app.exec())

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【资源说明】 基于python+pyside6的密码管理器源码(含使用说明).zip 多用户使用 数据本地化管理 本地存储使用多种加密方式 开发初衷 很多小伙伴应该都有被盗号的经历吧。首先有些黑客不得不说确实非常厉害,轻轻松松就能把你的账号盗走。 但是也存在自己慢慢实在太简单了,这种密码叫做弱密码,就比如说123456这种密码。 怎么说呢,这种密码确实很容易记,不知道您清不清楚这种密码在很多爆破字典中都是第一个,也就意味着,别人只要一式就知道你的密码了。 也就被盗了。 怎么说呢,这种情况是真的存在的,虽然这种电脑软件可能没那么实用,毕竟更多人用的都是手机,但是吧! 俺不会开发APP,我不是程序员,俺只会Python。 当然有的小伙伴可能会说开发网站,小程序什么的,这个的话还真不行,虽然我可以做,但是就算做出来,我自己都不会存。因为这些都会需要在服务器中,这种要是这个服务器被黑客攻击呢!不可控因素太多了! 我们生活在这透明的世界上,虽然没有隐私可言,但是还是保护一下自己,不要再用那种弱密码了。 实现功能 准备工作 您需要准备以下东西 Python3.9 及以上版本(或自行改写旧版不兼容的语法) peewee 3.15.3 pycryptodome 3.15.0 或其等价替代 PySide6 6.3.2 部分版本需要自行修改窗口移动代码,会存在不兼容 如何使用 源码运行 执行 pip install -r requirements.txt 即可安装依赖 main.py 运行主文件 path.py 项目路径管理 login.py 用户注册登录 model.py orm数据库 Global/GlobalVariable.py 全局变量[除level外不建议修改, 一般运行请将其设置为INFO] 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
PySide6 中,可以使用 QThread 和信号槽机制来实现多线程通信。下面是一个简单的例子: ```python from PySide6.QtCore import QObject, QThread, Signal class Worker(QObject): finished = Signal() progress = Signal(int) def run(self): for i in range(1, 11): self.progress.emit(i * 10) QThread.sleep(1) self.finished.emit() class Main(QObject): def __init__(self): super().__init__() self.worker = Worker() self.thread = QThread() self.worker.moveToThread(self.thread) self.worker.finished.connect(self.on_finished) self.worker.progress.connect(self.on_progress) self.thread.started.connect(self.worker.run) def start(self): self.thread.start() def on_progress(self, value): print(f"Progress: {value}%") def on_finished(self): print("Finished") if __name__ == "__main__": main = Main() main.start() ``` 在这个例子中,我们创建了两个 QObject 类,一个是 Worker,一个是 Main。Worker 类用于执行耗时的任务,Main 类用于启动和管理 Worker 类的线程。Worker 类中定义了两个信号,一个是进度信号 progress,一个是完成信号 finished。在 run 方法中,我们使用 sleep 方法模拟了一个耗时的任务,并在循环中发射了 progress 信号。 在 Main 类中,我们创建了一个 Worker 实例和一个 QThread 实例,并将 Worker 实例移动到了 QThread 中。我们通过连接信号和槽的方式监听 Worker 实例发射的信号,当 progress 信号被发射时,会调用 on_progress 方法打印进度信息,当 finished 信号被发射时,会调用 on_finished 方法打印完成信息。 最后,我们在 if __name__ == "__main__" 中创建了 Main 实例,并调用 start 方法启动线程。这样就可以在多线程环境下执行任务并实现通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值