Qt for Python做一个虚拟示波器软件

摘要

示波器是一种用来将电信号转化为可视化图形的智能仪器,在物理学中尤为常见。20世纪70年代以来,微电子技术和微信计算机技术的快速发展,使电子仪器的整体水平发生了很大变化。自微处理器问世后,先后出现了独立式智能仪器及自动测试系统、个人仪器系统。随着个人计算机算力的不断增强,虚拟化成为电子仪器的一个发展方向。本文用社区版qt creator5.0.2软件设计制作了示波器虚拟软件,由于时间仓促,仅实现了部分基本功能,仅供参考。

关键词:示波器;虚拟仪器;虚拟软件;

1. Qt

Qt是常用的一种ui设计软件,包含了大量的控件类,并以直观的方式展示出来。同时,其附带的Qt Designer 可以从左边的控件类库直接拖动控件到设计面板,所见即所得,大大节省了计算坐标优化窗口界面布局的工作,而且里面的控件风格都比较现代,更有美感。

1.1 Qt Creator 5.0.2 Community

Qt是一款商业软件,所以用于商业盈利涉及版权问题。但是对于非盈利个人也有社区开源版——Qt Creator 5.0.2 Community,本人用的是5.0.2版本。不附安装教程,CSDN内相关资料很多。
Qt Creator 5.0.2 Community欢迎界面:
Qt欢迎界面

1.2 创建Qt工程

点击"Project"边上的"+New"创建新的工程。
在这里插入图片描述

原本是打算用C++的,但是考虑到要用到画图功能,所以改注意用Python。在新建工程中选择"Applicaton(Qt for Python)“,然后再选择"Qt for Python - Window(UI file)”,这是生成一个Windows桌面软件的工程,默认自带了一个空的ui文件。
在这里插入图片描述
这里输入工程名称、选择工程创建路径。
在这里插入图片描述
来到这一步,可以不改。但是我想创建一个主窗口,所以"Base class"我改成了"QMainWindow"。
在这里插入图片描述
后面都可以一路"Next"。

1.3 UI设计

可以使用项目自动生成的.ui文件进行设计,需要额外的ui时可以新建文件,选择ui类型的文件。如下图:
在这里插入图片描述
一顿操作猛如虎,就得到了如下的ui界面:
在这里插入图片描述

1.4 ui文件转py文件

因为前面生成的是.ui文件,在python文件中是不能直接调用的。所以我们需要将.ui文件转为.py文件,方便import。

这时需要启动Terminal,然后cd命令转到设计好的.ui文件所在的文件目录下,输入如下指令:

pyuic5 -o filename.py filename.ui

前面filename是.ui文件名,后一个filename是目标文件名。这样我们就得到了ui界面的py文件。下面就是开始编写代码了。

2. 程序

2.1 import

from numpy import *
from matplotlib import pyplot
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib
matplotlib.use("Qt5Agg")  # 声明使用QT5
from PyQt5.QtWidgets import QApplication,QMainWindow,QGridLayout,QGraphicsScene,QSizePolicy,qApp
import win32api
import win32con
from PyQt5 import QtCore,QtGui
import sys
import MainWindow	#引入ui文件生成的py文件

2.2 窗口类

class MainWin(QMainWindow,MainWindow.Ui_MainWindow):#继承MainWindow的Ui_MainWindow类
    def __init__(self):		#构造函数
        super(MainWin,self).__init__()
        self.setupUi(self)
        self.setWindowTitle("简易示波器")

开始想到将控件在main()函数里实现功能,但后来发现,面向对象编程才是最方便的,也是逻辑最清晰的,所以将控件的功能函数作为成员函数来实现。

class MainWin(QMainWindow,MainWindow.Ui_MainWindow):
    def __init__(self):
        super(MainWin,self).__init__()
        self.setupUi(self)
        self.setWindowTitle("简易示波器")
        self.F=MyPicture(X1,dX,C,A)#创建主窗口类下的Picture对象,窗口被创建时创建一个Picture对象
        self.setWindowIcon(QtGui.QIcon("./OSC.ico"))
        self.gridlayout = QGridLayout(self.groupBox_2)  # 继承容器groupBox_2
        self.gridlayout.addWidget(self.F,0,1)#在groupBox_2中添加Picture对象
        self.dial_4.setValue(100)#时间轴旋钮初值
        self.dial_5.setValue(20)#x轴平移旋钮初值
        self.dial_6.setValue(20)
        self.pushButton_3.clicked.connect(self.ResetKey)#Auto键
        self.horizontalSlider_3.sliderMoved.connect(self.t1_slide)#t1滑条信号
        self.horizontalSlider_4.sliderMoved.connect(self.t2_slide)#t2滑条信号
        self.dial_6.valueChanged.connect(self.TimerMove)#时间轴旋钮信号
        self.lineEdit.setPlaceholderText("在这里输入自定义函数")
        self.dial_5.valueChanged.connect(self.AmpliMove)#幅值旋钮信号
        self.dial_7.valueChanged.connect(self.XaxisMove)#X平移旋钮信号
        self.dial_4.valueChanged.connect(self.YaxisMove)#Y平移旋钮信号
        self.actionExit.triggered.connect(qApp.quit)    #菜单栏退出信号
        self.actionSin_x.triggered.connect(self.actSin_x)   #选择正弦波
        self.actionxsin_x.triggered.connect(self.actxsin_x) #选择xsin(x)波
        self.actionSquare_Wave.triggered.connect(self.actSquareWave)    #选择方波
        self.actionTriangle_Wave.triggered.connect(self.actTriangleWave)    #选择三角波
        self.actionSawtooth_Wave.triggered.connect(self.actsawtoothWave)    #选择锯齿波
        self.pushButton.clicked.connect(self.actMyselfWaveInput)            #确认输入的公式
        self.radioButton_3.clicked.connect(self.CH1Pross)#信道1信号
        self.radioButton_4.clicked.connect(self.CH2Pross)#信道2信号

成员函数主要有以下内容,由于作业为提交,这里就暂不放完整源代码了。
在这里插入图片描述

2.3 信号类VirtualSignal

class VirtualSignal():
    def __init__(self):#略
    def changesig(self):    #更改信号,略
    def changesigA(self):    #更改幅值,略
    def changesigC(self):    #更改偏移,略

此类在MainWin类中实现,用于描述信道信号,便于操作信号。

2.4 画布类

#定义画布类,继承FigureCanvasQTAgg
class MyFigure(FigureCanvas):
    def __init__(self,parent=None):
        fig=Figure(figsize=(77,50),dpi=100) #定义画布
        super(MyFigure,self).__init__(fig)  #继承父类
        self.axes=fig.add_subplot(111)      #定义图像
        self.compute_initial_figure()
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,QSizePolicy.Expanding,QSizePolicy.Expanding)#图像大小
        FigureCanvas.updateGeometry(self)   #更新画布

    def compute_initial_figure(self):
        pass

2.5 图像类

#图像子类,继承画布类
class MyPicture(MyFigure):
    def __init__(self,x1,dx,c,a):   #构造函数
        super(MyPicture,self).__init__()
        self.x1=x1                  #初始化坐标
        self.dx=dx                  #初始化坐标轴大小
        self.x2=self.x1+self.dx
        CH1=VirtualSignal(a,c)      #信号类对象,信道1
        CH2=VirtualSignal(a,c)      #信号类对象,信道2
        self.CH=[CH1,CH2]
        self.xindao=0               #信道序号
        self.t1=T1                  #t1滑条初始位置
        self.t2=T2                  #t2滑条初始位置
        self.update_figure()        #更新画布
	def changex(self):          #横向滑动坐标轴,略
	def changeTimer(self):       #放缩坐标轴,略
	def changeC(self):           #更改偏移量,略
	def changeA(self):           #更改幅值,略
	def t1SlideChange(self):     #操作时间滑条t1,略
	def t2SlideChange(self):     #操作时间滑条t2,略
	def changesignal(self):      #更换信道信号,略
	def update_figure(self):            #更新画布,略

这里就体现了类的优点,每个对象的函数都定义在了类里,这样就不会使main函数过于臃肿,而且当需要修改类的成员时,也不需要整个文件修改,只需要在类里修改,条理清晰,更为整洁。

2.6 全局变量

X1=0.0	#坐标轴起始位置
dX=20.0	#坐标轴宽度
C=0.0	#图像上下平移的刻度
A=1.0	#幅值
T1=0	#t1滑条的值
T2=100	#t2滑条的值

SineWave="sin(x)"	#正弦波表达式
xcosWave="cos(x)*x"	#复合函数1
xsinWave="sin(x)*x"	#复合函数2
SquareWave="where(x%4.0<2,-1.0,1.0)"	#方波,where函数是numpy库里的函数
TriangleWave="where(x%8<=4,x%8,8-x%8)"	#三角波
SawToothWave="where(x%6<6,x%4,0)"		#锯齿波

2.7 主函数

mian函数主要作用是将窗口类实现,其余相关操作都以成员函数的方式定义在了相应的类里,这样,main函数就简单了不少。

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui=MainWin()	#窗口类的实现对象
    ui.show()		#显示窗口
    sys.exit(app.exec_())	#退出

最终,整个程序的结构如下:
在这里插入图片描述

3. 结果

在这里插入图片描述
一开始的想法是制作动态的图像,但是由于让图像保持动态无法避免地导致计算机重复刷新而使其他操作的相应卡顿,所以最终选择了静态。也可以尝试动态,只需要修改图像类和画布类即可。参照这篇文章可以实现动态效果。

由于这是作业尚未提交,暂不附源代码,有问题欢迎沟通。

  • 7
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Qt6是一款流行的跨平台开发工具,可以用于编写实时示波器程序。实时示波器能够采集和显示电信号或其他类型的实时数据,可用于调试和诊断各种电子、电气和机械系统。下面给出一个实时示波器程序的编写思路。 1. 定义采样率和采样精度。示波器的效果和响应速度取决于采样率和采样精度,因此需要根据所需的应用场景进行选择。 2. 选择合适的数据输入设备和数据传输方式。可以使用网络接口、串口或USB设备等手段来获取数据,并通过Qt提供的数据传输库进行数据传输。 3. 定义数据显示界面。实时示波器的核心是数据的实时显示,Qt提供了多种界面元素,如窗口、控件和布局等,可用于设计各种数据显示和控制界面。 4. 利用Qt提供的图形绘制和显示功能,在画布上绘制波形图。可以采用多种绘图方式,如折线图、散点图和柱状图等,同时还可添加坐标轴、标签和注释等图形元素,以方便用户观察和分析数据。 5. 设计用户界面的交互行为。可以通过按钮、滑动条等控件实现数据显示的控制,如选择采样率、采样精度和数据范围等。 6. 添加数据处理和分析功能。实时示波器通常需要进行数据处理和分析,如滤波、峰值检测、FFT变换等,以方便用户获取更多的有用信息。 7. 最后进行优化和测试,以保证程序的可靠性和性能。 综上所述,Qt6可以用于开发实时示波器程序,并且可以根据需要进行灵活的定制和扩展。欢迎有需要的用户进行尝试和应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武的阶乘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值