pyqt5?子線程如何操作主線程GUI(示例代碼)
一.簡介
在使用pyqt5編寫gui時遇到兩個問題,會導(dǎo)致界面崩潰,今天就圍繞這兩個問題來簡單說明和改進(jìn)。
1.在主線程中使用while無限循環(huán)會導(dǎo)致界面崩潰
2.在子線程中操作主線程gui會導(dǎo)致界面崩潰
二.步驟說明
1.在主線程中使用while無限循環(huán)會導(dǎo)致界面崩潰
1)錯誤代碼
import sys
from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget
class FileChooserApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
button = QPushButton("按鈕")
self.reviewEdit = QTextEdit()
self.reviewEdit.move(100, 100)
button.clicked.connect(self.send)
hbox1 = QHBoxLayout() # 創(chuàng)建一個水平布局
hbox1.addWidget(button) # 添加按鈕到水平布局中
hbox1.addStretch(1) # 設(shè)置水平比例間距
hbox1.addWidget(self.reviewEdit) # 添加按鈕到水平布局中
self.setLayout(hbox1) # 添加到布局器
self.setWindowTitle('文件選擇器')
self.setGeometry(300, 300, 500, 500)
def send(self):
"""
事件
:return:
"""
while True:
"""
邏輯代碼
"""
self.reviewEdit.setText("測試")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = FileChooserApp()
ex.show()
sys.exit(app.exec_())2)崩潰原因
我們先來說下while崩潰的問題,這邊我設(shè)置的循環(huán)是一個無限循環(huán),不會給 GUI 事件循環(huán)任何運行的機(jī)會。在 PyQt 或其他 GUI 框架中,GUI 的事件循環(huán)(例如按鈕點擊、窗口移動等)必須在單獨的線程中運行,以保持 GUI 的響應(yīng)性
3)改進(jìn)方法
將循環(huán)體在一個子線程中執(zhí)行,就可以避免這個問題,代碼如下。
import sys
import threading
from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget
class FileChooserApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
button = QPushButton("按鈕")
self.reviewEdit = QTextEdit()
self.reviewEdit.move(100, 100)
button.clicked.connect(self.send)
hbox1 = QHBoxLayout() # 創(chuàng)建一個水平布局
hbox1.addWidget(button) # 添加按鈕到水平布局中
hbox1.addStretch(1) # 設(shè)置水平比例間距
hbox1.addWidget(self.reviewEdit) # 添加按鈕到水平布局中
self.setLayout(hbox1) # 添加到布局器
self.setWindowTitle('文件選擇器')
self.setGeometry(300, 300, 500, 500)
def send(self):
"""
事件
:return:
"""
def send_a():
while True:
"""
邏輯代碼
"""
print("123")
send_thread = threading.Thread(target=send_a)
# 啟動線程
send_thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = FileChooserApp()
ex.show()
sys.exit(app.exec_())2.在子線程中操作主線程gui會導(dǎo)致界面崩潰
1)錯誤代碼
import sys
import threading
import time
from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget
class FileChooserApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
button = QPushButton("按鈕")
self.reviewEdit = QTextEdit()
self.reviewEdit.move(100, 100)
button.clicked.connect(self.send)
hbox1 = QHBoxLayout() # 創(chuàng)建一個水平布局
hbox1.addWidget(button) # 添加按鈕到水平布局中
hbox1.addStretch(1) # 設(shè)置水平比例間距
hbox1.addWidget(self.reviewEdit) # 添加按鈕到水平布局中
self.setLayout(hbox1) # 添加到布局器
self.setWindowTitle('文件選擇器')
self.setGeometry(300, 300, 500, 500)
def send(self):
"""
事件
:return:
"""
def send_a():
while True:
"""
邏輯代碼
"""
self.reviewEdit.setText("設(shè)置文案")
send_thread = threading.Thread(target=send_a)
# 啟動線程
send_thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = FileChooserApp()
ex.show()
sys.exit(app.exec_())2)崩潰原因
上述中試圖在子線程send_a方法中給文本編輯器設(shè)置文案。這是不允許的,因為 PyQt 和大多數(shù) GUI 框架一樣,要求所有的 GUI 更新必須在主線程(也稱為 GUI 線程)中執(zhí)行。
3)改進(jìn)方法
既然在子線程中無法操作主線程gui更新,那么只能在主線程中去執(zhí)行,這就需要信號與槽的配合了。我們先來自定義一個信號
class YourThread(QObject):
show_warning_signal = pyqtSignal()
def run(self):
self.show_warning_signal.emit()在初始化的時候去實例化YourThread類,連線信號與槽
class FileChooserApp(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.your = YourThread()
self.your.show_warning_signal.connect(self.settext)接著在子線程中直接去觸發(fā)信號即可
def send(self):
def send_a():
while True:
"""
循環(huán)體
"""
self.your.run()
time.sleep(2)
send_thread = threading.Thread(target=send_a)
# 啟動線程
send_thread.start()執(zhí)行每次循環(huán)需要等待2s,避免出現(xiàn)無限循環(huán)導(dǎo)致應(yīng)用程序凍結(jié)、響應(yīng)緩慢或其他線程相關(guān)的問題
三.實例
import sys
import threading
import time
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget
class YourThread(QObject):
show_warning_signal = pyqtSignal()
def run(self):
self.show_warning_signal.emit()
class FileChooserApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.your = YourThread()
self.your.show_warning_signal.connect(self.settext)
def initUI(self):
button = QPushButton("按鈕")
self.reviewEdit = QTextEdit()
self.reviewEdit.move(100, 100)
button.clicked.connect(self.send)
hbox1 = QHBoxLayout() # 創(chuàng)建一個水平布局
hbox1.addWidget(button) # 添加按鈕到水平布局中
hbox1.addStretch(1) # 設(shè)置水平比例間距
hbox1.addWidget(self.reviewEdit) # 添加按鈕到水平布局中
self.setLayout(hbox1) # 添加到布局器
self.setWindowTitle('文件選擇器')
self.setGeometry(300, 300, 500, 500)
def send(self):
"""
事件
:return:
"""
def send_a():
while True:
"""
邏輯代碼
"""
self.your.run()
time.sleep(2)
send_thread = threading.Thread(target=send_a)
# 啟動線程
send_thread.start()
def settext(self):
self.reviewEdit.setText("123")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = FileChooserApp()
ex.show()
sys.exit(app.exec_())到此這篇關(guān)于pyqt5 子線程如何操作主線程GUI的文章就介紹到這了,更多相關(guān)pyqt5 子線程操作主線程GUI內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中的插值 scipy-interp的實現(xiàn)代碼
這篇文章主要介紹了python中的插值 scipy-interp的實現(xiàn)代碼,需要的朋友可以參考下2018-07-07
python利用跳板機(jī)ssh遠(yuǎn)程連接redis的方法
今天小編就為大家分享一篇python利用跳板機(jī)ssh遠(yuǎn)程連接redis的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-02-02
python人工智能tensorflow函數(shù)tensorboard使用方法
這篇文章主要為大家介紹了python人工智能tensorflow函數(shù)tensorboard使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

