參考:https://blog.csdn.net/zx520113/article/details/86598658
PyQt5中使用QTimer定時刷新:當要執(zhí)行可能會超過設定時間的代碼
一、頁面刷新
刷新界面命令: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_())
對于執(zhí)行很耗時的程序來說,由于PyQt需要等待程序執(zhí)行完畢才能進行下一步,這個過程表現在界面上就是卡頓,而如果需要執(zhí)行這個耗時程序時不斷的刷新界面。那么就可以使用QApplication.processEvents(),那么就可以一邊執(zhí)行耗時程序,一邊刷新界面的功能,給人的感覺就是程序運行很流暢,因此QApplicationEvents()的使用方法就是,在主函數執(zhí)行耗時操作的地方,加入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) #到達設定的時間后,執(zhí)行槽函數代碼
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('開始執(zhí)行了-----')
def endTimer(self):
self.timer.stop() --停止
def myFunction(self):
# for i in range(10):
# self.label.setText(str(i) + ',')
#如果執(zhí)行該代碼的時間遠遠超過 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界面刷新(表格數據刷新)、界面?zhèn)髦?、卡頓
PyQt5 實時刷新數據
解決PySide6/PyQT的界面卡死問題(PySide6/PyQT多線程
在PySide6中,可以使用這些線程類去(QThread、QObject、QRunnable 和 QtConcurrent)創(chuàng)建線程多線程,并采用 信號和槽機制 來將線程中的結果回傳到主線程。
本文用 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)
# 處理業(yè)務邏輯
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):
# 創(chuàng)建線程
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() 方法被調用時,就會自動執(zhí)行該方法。
觸發(fā) initUI 方法,在該方法中會創(chuàng)建線程類 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
#業(yè)務代碼
self.valueChange.emit(i)
self.msleep(100)
#線程鎖off
self.mutex.unlock()
class MyDialog(QDialog):
def __init__(self):
super().__init__()
"""控件的創(chuàng)建和布局"""
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()#創(chuàng)建線程
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() # 創(chuàng)建鎖
lock. acquire() # 鎖定
lock. release() # 釋放
比如線程t1使用lock.acquire()獲得了這個鎖,那么線程t2就無法再獲得該鎖了,只會阻塞在 lock.acquire()處,直到鎖被線程t1釋放,即執(zhí)行l(wèi)ock.release()。如此一來就不會出現執(zhí)行了一半就暫停去執(zhí)行別的線程的情況,起到保護作用,直至釋放該鎖,其他的線程或進程才可以成功獲取該鎖,然后繼續(xù)執(zhí)行下面的代碼塊。
"""
進程:正在運行的程序
線程: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
# 創(chuàng)建第一個線程類
class Thread1(QThread):
def run(self):
for i in range(10):
print("Thread 1: ", i)
# 創(chuàng)建第二個線程類
class Thread2(QThread):
def run(self):
for i in range(10):
print("Thread 2: ", i)
# 創(chuàng)建線程對象并啟動線程
thread1 = Thread1()
thread2 = Thread2()
thread1.start()
thread2.start()
創(chuàng)建了兩個線程類Thread1和Thread2,分別重寫了run方法來定義線程的具體功能。然后創(chuàng)建了兩個線程對象,并通過調用start()方法來啟動線程。通過這樣的方式,就可以同時運行兩個不同的線程。文章來源:http://www.zghlxwxcb.cn/news/detail-843259.html
線程之間的通信
from PyQt5.QtCore import QThread, pyqtSignal
# 創(chuàng)建第一個線程類
class Thread1(QThread):
# 定義自定義信號
my_signal = pyqtSignal(str)
def run(self):
for i in range(10):
self.my_signal.emit("Thread 1: " + str(i))
# 創(chuàng)建第二個線程類
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)
# 創(chuàng)建線程對象并啟動線程
thread1 = Thread1()
thread2 = Thread2()
thread1.start()
thread2.start()
在Thread1類中定義了一個自定義信號my_signal,并在run方法中使用emit方法發(fā)出信號。在Thread2類中, 用connect方法將自定義信號和槽函數handle_signal綁定在一起,實現信號的接收和處理。通過這樣的方式, 可以在兩個線程之間實現通信。文章來源地址http://www.zghlxwxcb.cn/news/detail-843259.html
到了這里,關于python--pyQt5 頁面刷新\線程刷新\界面卡頓 --- 多線程處理(線程的開始/暫停/恢復/取消)同時運行兩個不同的線程 pyside6的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!