参考:https://blog.csdn.net/zx520113/article/details/86598658
PyQt5中使用QTimer定时刷新:当要执行可能会超过设定时间的代码
一、页面刷新
刷新界面命令:QApplication.processEvents()
import sys
from PyQt5.QtWidgets import *
import time
class WinForm(QWidget):
def __init__(self, parent = None):
super(WinForm, self).__init__(parent)
self.setWindowTitle('实时刷新页面例子')
self.listFile = QListWidget()
self.btnStart = QPushButton('开始')
layout = QGridLayout(self)
layout.addWidget(self.listFile, 0, 0, 1, 2)
layout.addWidget(self.btnStart, 1, 1)
self.btnStart.clicked.connect(self.slotAdd)
self.setLayout(layout)
def slotAdd(self):
for n in range(10):
str_n = 'file index {0}'.format(n)
self.listFile.addItem(str_n)
QApplication.processEvents()
time.sleep(1)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
对于执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿,而如果需要执行这个耗时程序时不断的刷新界面。那么就可以使用QApplication.processEvents(),那么就可以一边执行耗时程序,一边刷新界面的功能,给人的感觉就是程序运行很流畅,因此QApplicationEvents()的使用方法就是,在主函数执行耗时操作的地方,加入QApplication.processEvents()
QTimer
#定义QTimer 类
self. Timer = QTimer(self)
self.timer.start(1000) #单位为毫秒
self. Stop()
需要定时对数据进行刷新,以获取到最新的数据,然后对数据进行处理, 这时候可以采用PyQT5 中的QTimer 类
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QGridLayout, QLabel
from PyQt5.QtCore import QTimer
import sys
class WinForm(QWidget):
def __init__(self, parent=None):
super(WinForm, self).__init__(parent)
self.setWindowTitle("QTimer demo")
self.label = QLabel('测试')
self.startBtn = QPushButton('开始')
self.endBtn = QPushButton('结束')
layout = QGridLayout(self)
# 初始化一个定时器
self.timer = QTimer(self)
self.timer.timeout.connect(self.myFunction) #到达设定的时间后,执行槽函数代码
layout.addWidget(self.label, 0, 0, 1, 2)
layout.addWidget(self.startBtn, 1, 0)
layout.addWidget(self.endBtn, 1, 1)
# 连接按键操作和槽函数
self.startBtn.clicked.connect(self.startTimer)
self.endBtn.clicked.connect(self.endTimer)
self.setLayout(layout)
def startTimer(self):
self.timer.start(5000) # 5000 单位是毫秒, 即 5 秒 --开始
self.label.setText('开始执行了-----')
def endTimer(self):
self.timer.stop() --停止
def myFunction(self):
# for i in range(10):
# self.label.setText(str(i) + ',')
#如果执行该代码的时间远远超过 5 秒的话: 使用下面的方法
self.timer.stop()
for i in range(100000000): #此代码远远超过 5 秒
if i % 100 == 0:
print(i)
self.label.setText('这是很长的代码')
self.timer.start() #此时, start 中不要加任何的时间
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
二、多线程处理(线程刷新)-- QThread
pyqt界面刷新(表格数据刷新)、界面传值、卡顿
PyQt5 实时刷新数据
解决PySide6/PyQT的界面卡死问题(PySide6/PyQT多线程
在PySide6中,可以使用这些线程类去(QThread、QObject、QRunnable 和 QtConcurrent)创建线程多线程,并采用 信号和槽机制 来将线程中的结果回传到主线程。
本文用 QThread,它继承了 QObject
界面里函数运行多次的话,移动窗口有种卡顿的感觉,还是使用 线程刷新 比较合适
from PyQt5.QtCore import QThread, pyqtSignal, QDateTime, QObject
from PyQt5.QtWidgets import QApplication, QDialog, QLineEdit, QLabel
import time
import sys
class BackendThread(QObject):
# 通过类成员对象定义信号
update_date = pyqtSignal(str)
# 处理业务逻辑
def run(self):
while 1:
# 刷新1-10
for i in range(1, 11):
print(f"开始处理第{i + 1}个...")
self.update_date.emit(str(i))
time.sleep(1)
class Window(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setWindowTitle('PyQt 5界面实时更新例子')
self.resize(400, 100)
self.input = QLabel(self)
self.input.resize(400, 100)
self.initUI()
def initUI(self):
# 创建线程
self.thread = QThread()
self.backend = BackendThread()
# 连接信号
self.backend.update_date.connect(self.handleDisplay)
self.backend.moveToThread(self.thread)
# 开始线程
self.thread.started.connect(self.backend.run)
self.thread.start()
# 将当前时间输出到文本框
def handleDisplay(self, data):
self.input.setText(data)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
界面 和 运行 相分离,通过信号与槽来进行参数传递
重写的run方法,当线程的 start() 方法被调用时,就会自动执行该方法。
触发 initUI 方法,在该方法中会创建线程类 BackendThread 的实例并启动该线程。
三、多线程处理(线程的开始/暂停/恢复/取消)–QThread
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class Thread(QThread):
#线程值信号
valueChange = pyqtSignal(int)
#构造函数
def __init__(self):
super(Thread, self).__init__()
self.isPause = False
self.isCancel=False
self.cond = QWaitCondition()
self.mutex = QMutex()
#暂停
def pause(self):
print("线程暂停")
self.isPause = True
#恢复
def resume(self):
print("线程恢复")
self.isPause = False
self.cond.wakeAll()
#取消
def cancel(self):
print("线程取消")
self.isCancel=True
#运行(入口)
def run(self):
for i in range(100):
#线程锁on
self.mutex.lock()
if self.isPause:
self.cond.wait(self.mutex)
if self.isCancel:
self.valueChange.emit(0)
break
#业务代码
self.valueChange.emit(i)
self.msleep(100)
#线程锁off
self.mutex.unlock()
class MyDialog(QDialog):
def __init__(self):
super().__init__()
"""控件的创建和布局"""
self.layout=QVBoxLayout(self)
self.progressBar=QProgressBar()
self.btnBegin=QPushButton("开始")
self.btnPause=QPushButton("暂停")
self.btnPause.setEnabled(False)
self.btnResume=QPushButton("恢复")
self.btnResume.setEnabled(False)
self.btnCancel=QPushButton("取消")
self.btnCancel.setEnabled(False)
self.layout.addWidget(self.progressBar)
self.layout.addWidget(self.btnBegin)
self.layout.addWidget(self.btnPause)
self.layout.addWidget(self.btnResume)
self.layout.addWidget(self.btnCancel)
"""信号绑定"""
self.btnBegin.clicked.connect(self.__onClickedBtnbegin)
self.btnPause.clicked.connect(self.__onClickedBtnpause)
self.btnResume.clicked.connect(self.__onClickedBtnresume)
self.btnCancel.clicked.connect(self.__onClickedBtncancel)
#开始按钮被点击的槽函数
def __onClickedBtnbegin(self):
self.btnBegin.setEnabled(False)
self.btnPause.setEnabled(True)
self.btnResume.setEnabled(False)
self.btnCancel.setEnabled(True)
self.thread=Thread()#创建线程
self.thread.valueChange.connect(self.progressBar.setValue)#线程信号和槽连接
self.thread.start()
#暂停按钮被点击的槽函数
def __onClickedBtnpause(self):
self.btnBegin.setEnabled(False)
self.btnPause.setEnabled(False)
self.btnResume.setEnabled(True)
self.btnCancel.setEnabled(True)
self.thread.pause()
#恢复按钮被点击的槽函数
def __onClickedBtnresume(self):
self.btnBegin.setEnabled(False)
self.btnPause.setEnabled(True)
self.btnResume.setEnabled(False)
self.btnCancel.setEnabled(True)
self.thread.resume()
#取消按钮被点击的槽函数
def __onClickedBtncancel(self):
self.btnBegin.setEnabled(True)
self.btnPause.setEnabled(False)
self.btnResume.setEnabled(False)
self.btnCancel.setEnabled(False)
self.thread.cancel()
if __name__=="__main__":
#qt程序
app=QApplication(sys.argv)
dialog=MyDialog()
dialog.show()
sys.exit(app.exec_())
四、线程锁
lock = threading.RLock() # 创建锁
lock. acquire() # 锁定
lock. release() # 释放
比如线程t1使用lock.acquire()获得了这个锁,那么线程t2就无法再获得该锁了,只会阻塞在 lock.acquire()处,直到锁被线程t1释放,即执行lock.release()。如此一来就不会出现执行了一半就暂停去执行别的线程的情况,起到保护作用,直至释放该锁,其他的线程或进程才可以成功获取该锁,然后继续执行下面的代码块。
"""
进程:正在运行的程序
线程:cpu调度的单位,一个进程可以包含多个线程
多线程: 合适IO密集型
多进程: cpu密集型任务
"""
import threading
import time
lock = threading.RLock()
def my_print(name):
for i in range(10):
time.sleep(1)
lock.acquire()
print(name, i)
lock.release()
start = time.time() # 返回当前的时间戳
t1 = threading.Thread(target=my_print, args=["threading1:"]) # 传个任务,和参数进来
t2 = threading.Thread(target=my_print, args=['threading2:'])
t1.start() # 线程开始
t2.start()
t1.join()
t2.join()
end = time.time()
print(end - start)
print("结束")
五、同时运行两个不同的线程
https://geek-docs.com/pyqt/pyqt-questions/202_pyqt_how_run_two_different_threads_simultaneously_in_pyqt.html
from PyQt5.QtCore import QThread
# 创建第一个线程类
class Thread1(QThread):
def run(self):
for i in range(10):
print("Thread 1: ", i)
# 创建第二个线程类
class Thread2(QThread):
def run(self):
for i in range(10):
print("Thread 2: ", i)
# 创建线程对象并启动线程
thread1 = Thread1()
thread2 = Thread2()
thread1.start()
thread2.start()
创建了两个线程类Thread1和Thread2,分别重写了run方法来定义线程的具体功能。然后创建了两个线程对象,并通过调用start()方法来启动线程。通过这样的方式,就可以同时运行两个不同的线程。文章来源:https://www.toymoban.com/news/detail-843259.html
线程之间的通信
from PyQt5.QtCore import QThread, pyqtSignal
# 创建第一个线程类
class Thread1(QThread):
# 定义自定义信号
my_signal = pyqtSignal(str)
def run(self):
for i in range(10):
self.my_signal.emit("Thread 1: " + str(i))
# 创建第二个线程类
class Thread2(QThread):
def __init__(self):
super().__init__()
self.my_signal.connect(self.handle_signal)
def handle_signal(self, msg):
print(msg)
def run(self):
for i in range(10):
print("Thread 2: ", i)
# 创建线程对象并启动线程
thread1 = Thread1()
thread2 = Thread2()
thread1.start()
thread2.start()
在Thread1类中定义了一个自定义信号my_signal,并在run方法中使用emit方法发出信号。在Thread2类中, 用connect方法将自定义信号和槽函数handle_signal绑定在一起,实现信号的接收和处理。通过这样的方式, 可以在两个线程之间实现通信。文章来源地址https://www.toymoban.com/news/detail-843259.html
到了这里,关于python--pyQt5 页面刷新\线程刷新\界面卡顿 --- 多线程处理(线程的开始/暂停/恢复/取消)同时运行两个不同的线程 pyside6的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!