PyQt5(四) 线程与绘图处理
线程与绘图处理
参考文章:https://blog.csdn.net/liming89/article/details/109576602
引出问题:
import sys import time from PyQt5.QtWidgets import QMainWindow,QWidget,QApplication,QMessageBox from PyQt5.uic import loadUi class DemoWin(): def __init__(self): self.ui=loadUi("../ui/task.ui") self.ui.button1.clicked.connect(self.clicked_one) self.ui.button2.clicked.connect(self.clicked_two) def clicked_one(self): print("Hello world...") time.sleep(10) def clicked_two(self): print("开始执行。。") QMessageBox.information(self.ui,"提示","哈哈哈") if __name__ == '__main__': app=QApplication(sys.argv) obj=DemoWin() obj.ui.show() sys.exit(app.exec_())
问题:假设当操作一十分耗时的时候,剩下的加界面会卡住,无法操作,因此在使用的时候需要进行异步的设置。
1.界面阻塞
上述问题的原因是因为,我们的代码都是在主线程中执行的。
sys.exit(app.exec_()) # app.exec_() 其实会让主线程进入一个死循环,循环不断处理用户的操作事件
当我们点击发送按钮后,Qt 的核心代码就会收到这个点击事件,并调用相关的Slot 函数去处理。
self.ui.button1.clicked.connect(self.clicked_one)
如果 clicked_one
很快能接收到响应,那么 clicked_one 就可以很快返回,返回后, 整个程序又进入到 app.exec_() 里面接收各种 事件,并且调用相应的函数去处理。界面就不会僵死,因为所有的操作界面的事件,都能得到及时的处理。
但是,如果这个clicked_one
要很长时间才能返回,这段时间内,整个程序就停在 下面这行代码处
time.sleep(10)
自然就没有机会去处理其他的用户操作界面的事件了,当然程序就僵死了。
2.多线程处理
使用Python的原生线程进行操作,适当的时候可以使用函数的嵌套,闭包 进行参数的封装。
import sys import time from threading import Thread from PyQt5.QtWidgets import QMainWindow,QWidget,QApplication,QMessageBox from PyQt5.uic import loadUi class DemoWin(): def __init__(self): self.ui=loadUi("../ui/task.ui") self.ui.button1.clicked.connect(self.clicked_one) self.ui.button2.clicked.connect(self.clicked_two) def clicked_one(self): print("Hello world...") thread=Thread(target=self.run_task,args=(10,)) thread.start()# 设置线程为供cpu调度的状态 print("run success !!!") def run_task(self,t): time.sleep(t) print("异步任务执行完整") def clicked_two(self): print("开始执行。。") QMessageBox.information(self.ui,"提示","哈哈哈") if __name__ == '__main__': app=QApplication(sys.argv) obj=DemoWin() obj.ui.show() sys.exit(app.exec_())
- 补充:子线程发信号更新界面,请参考:
https://www.byhy.net/tut/py/gui/qt_08/
3.绘制图形
参考文章:https://blog.csdn.net/wuwei_201/article/details/106106387
import sys from PyQt5.QtWidgets import QApplication,QMainWindow,QWidget from PyQt5 import QtWidgets from PyQt5 import QtCore import numpy as np import matplotlib matplotlib.use("Qt5Agg") # 声明使用pyqt5 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg # pyqt5的画布 import matplotlib.pyplot as plt # matplotlib.figure 模块提供了顶层的Artist(图中的所有可见元素都是Artist的子类),它包含了所有的plot元素 from matplotlib.figure import Figure class MyMatplotlibFigure(FigureCanvasQTAgg): """ 创建一个画布类,并把画布放到FigureCanvasQTAgg """ def __init__(self, width=10, heigh=10, dpi=100): plt.rcParams['figure.facecolor'] = 'r' # 设置窗体颜色 plt.rcParams['axes.facecolor'] = 'b' # 设置绘图区颜色 # 创建一个Figure,该Figure为matplotlib下的Figure,不是matplotlib.pyplot下面的Figure self.figs = Figure(figsize=(width, heigh), dpi=dpi) super(MyMatplotlibFigure, self).__init__(self.figs) # 在父类种激活self.fig, self.axes = self.figs.add_subplot(111) # 添加绘图区 def mat_plot_drow_axes(self, t, s): """ 用清除画布刷新的方法绘图 :return: """ self.axes.cla() # 清除绘图区 self.axes.spines['top'].set_visible(False) # 顶边界不可见 self.axes.spines['right'].set_visible(False) # 右边界不可见 # 设置左、下边界在(0,0)处相交 # self.axes.spines['bottom'].set_position(('data', 0)) # 设置y轴线原点数据为 0 self.axes.spines['left'].set_position(('data', 0)) # 设置x轴线原点数据为 0 self.axes.plot(t, s, 'o-r', linewidth=0.5) self.figs.canvas.draw() # 这里注意是画布重绘,self.figs.canvas self.figs.canvas.flush_events() # 画布刷新self.figs.canvas class MainDialogImgBW_(QtWidgets.QMainWindow): """ 创建UI主窗口,使用画板类绘图。 """ def __init__(self): super(MainDialogImgBW_, self).__init__() self.setWindowTitle("显示matplotlib") self.setObjectName("widget") self.resize(800, 600) self.label = QtWidgets.QLabel(self) self.label.setGeometry(QtCore.QRect(0, 0, 800, 600)) self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100) self.plotcos() self.hboxlayout = QtWidgets.QHBoxLayout(self.label) self.hboxlayout.addWidget(self.canvas) def plotcos(self): # plt.clf() t = np.arange(0.0, 5.0, 0.01) s = np.cos(2 * np.pi * t) # self.canvas.aexs.plot(t, s) self.canvas.mat_plot_drow_axes(t, s) self.canvas.figs.suptitle("sin") # 设置标题 if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) main = MainDialogImgBW_() main.show() sys.exit(app.exec_())
创建画布类继承FigureCanvasQTAgg
,主窗口中添加上实例化,画图控件self.canvas
,绘制上对应数据即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix