一、基礎(chǔ)程序
以下簡(jiǎn)介一個(gè)基本的PyQt程序。
- 需要導(dǎo)入的類主要來(lái)自三個(gè)包
- from PyQt5.QtWidgets import 常用的控件
- PyQt5.QtCore 核心功能類,如QT,QThread,pyqtSignal
- PyQt5.QtGui UI類,如QFont
- 基礎(chǔ)的程序結(jié)構(gòu):
import sys
from PyQt5.QtWidgets import QApplication, QWidget
class Example(QWidget):
def __init__(self):
super().__init__()
self.setupUI()
def setupUI(self):
self.show()
pass
# 設(shè)置UI
if __name__ == '__main__':
app = QApplication(sys.argv) # 啟動(dòng)app
ex = Example() # 實(shí)例化一個(gè)自己派生的
# 也可以實(shí)例化庫(kù)中的控件
# q = QPushButton()
# q.show()
sys.exit(app.exec_())
二、Thread
方式一
//直接傳入函數(shù),啟動(dòng)線程,可以傳入?yún)?shù)
import time, threading
def threadFunction():
while True:
print(11111)
time.sleep()
# 用于命名,可以通過(guò)threading.current_thread().name獲得
t = threading.Thread(target=threadFunction, name='funciton')
# 如果線程有參數(shù)
t = threading.Thread(target=threadFunction, args=(), name='funciton')
t.start()
方式二
from threading import Thread
import time
class Example(Thread):
def __init__(self):
super().__init__()
def run(self):
while True:
time.sleep(1)
print(11111111)
if __name__ == '__main__':
a = Example()
a.start()
a.join()
print(222222222)
注意:
- 使用join方法會(huì)讓主線程阻塞在這里,等待子線程結(jié)束,在里面可以設(shè)置阻塞的時(shí)間
- a.setDaemon(True)在start前設(shè)置,可以保證在主線程終止時(shí),子線程也終止
三、信號(hào)機(jī)制
QT中的信號(hào)機(jī)制能夠方便的編寫(xiě)回調(diào)。
- 很多控件都有預(yù)定的信號(hào)如clicked,直接使用clicked.connect連接槽函數(shù)即可。
- 繼承自Qt的類,然后自定義一個(gè)signal類變量,在實(shí)例連接信號(hào)就可以了
class Example(QWidget):
signal = pyqtSignal() # 括號(hào)里填寫(xiě)信號(hào)傳遞的參數(shù)
# 發(fā)射信號(hào)
def func(self):
self.signal.emit()
# 使用信號(hào)
a = Example()
a.signal.connect(callback)
# 槽函數(shù)
def callback():
pass
四、UI刷新
在界面中,通常用會(huì)有一些按鈕,點(diǎn)擊后觸發(fā)事件,比如去下載一個(gè)文件或者做一些操作,這些操作會(huì)耗時(shí),如果不能及時(shí)結(jié)束,主線程將會(huì)阻塞,這樣界面就會(huì)出現(xiàn)未響應(yīng)的狀態(tài),因此必須使用多線程來(lái)解決這個(gè)問(wèn)題。
注意:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-666672.html
- PyQt5不能在子線程中刷新線程,這樣會(huì)造成界面卡死,因此不能使用常規(guī)的多線程刷新UI。
- 但是又必須要實(shí)現(xiàn)子線程和主線程之間的通信,否則無(wú)法得知任務(wù)是否完成。因此使用PyQt5中的QThread,這樣既可以使用信號(hào)機(jī)制,又能夠使用多線程。
- 當(dāng)啟動(dòng)多線程后,注冊(cè)信號(hào),槽函數(shù)為主線程中的函數(shù),當(dāng)任務(wù)完成后,發(fā)射信號(hào),在主線程中對(duì)UI進(jìn)行更新。
class Example(QThread):
signal = pyqtSignal() # 括號(hào)里填寫(xiě)信號(hào)傳遞的參數(shù)
def __init__(self):
super().__init__()
def __del__(self):
self.wait()
def run(self):
# 進(jìn)行任務(wù)操作
self.signal.emit() # 發(fā)射信號(hào)
# UI類中
def buttonClick(self)
self.thread = Example()
self.thread.signal.connect(self.callback)
self.thread.start() # 啟動(dòng)線程
def callbakc(self):
pass
五、moveToThread異步刷新UI
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import pyqtSignal, QObject, QThread
from QtUi import Ui_MainWindow
import sys
import time
class Work(QObject):
count = int(0)
count_signal = pyqtSignal(int)
def __init__(self):
super(Work, self).__init__()
self.run = True
def work(self):
self.run = True
while self.run:
print(str(self.count))
self.count += 1
self.count_signal.emit(self.count)
time.sleep(1)
def work_stop(self):
self.run = False
class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUi(self)
self.pushButton_Start.clicked.connect(self.workStart)
self.pushButton_Stop.clicked.connect(self.workStop)
self.thread = QThread()
self.worker = Work()
self.worker.count_signal.connect(self.flush)
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.work)
self.thread.finished.connect(self.finished)
def flush(self, count):
self.label.setText(str(count))
def workStart(self):
print('button start.')
self.pushButton_Start.setEnabled(False)
self.thread.start()
def workStop(self):
print('button stop.')
self.worker.work_stop()
self.thread.quit()
def finished(self):
print('finish.')
self.pushButton_Start.setEnabled(True)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myshow = MyWindow()
myshow.show()
sys.exit(app.exec_())
QtUi.py文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-666672.html
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'QtUi.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(515, 208)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton_Start = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_Start.setGeometry(QtCore.QRect(280, 150, 92, 28))
self.pushButton_Start.setObjectName("pushButton_Start")
self.pushButton_Stop = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_Stop.setGeometry(QtCore.QRect(390, 150, 92, 28))
self.pushButton_Stop.setObjectName("pushButton_Stop")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(60, 50, 381, 41))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(28)
self.label.setFont(font)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_Start.setText(_translate("MainWindow", "開(kāi)始"))
self.pushButton_Stop.setText(_translate("MainWindow", "停止"))
self.label.setText(_translate("MainWindow", "0"))
到了這里,關(guān)于PyQt5 多線程和異步刷新UI的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!