PySide 或 PyQT:在 QThread 进程中使用信号和槽来更新 GUI QLabel

问题描述 投票:0回答:1

我正在使用 QThread 运行一个长进程。在此过程中,我向插槽发送信号。我希望该插槽使用 setText() 更新 QLabel。我已确保我的 QThread 进程位于单独的线程上,并且我的 message_updater 函数位于主线程上。

setText() 正在更新标签的文本,但它没有显示在 GUI 上。我做错了什么?

主.py

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from run_worker_thread import RunWorkerThread
from return_message_label import ReturnMessage

class MainWindow(QMainWindow):
    
    def __init__(self):
        super().__init__()        
        
        self.setWindowTitle("PaGWIS")
        self.setMinimumSize(800, 400)        
        layout = QVBoxLayout()
        
        widgets = [
            RunWorkerThread,
            ReturnMessage
        ]
        
        for w in widgets:
            layout.addWidget(w())
            
        widget = QWidget()
        widget.setLayout(layout)
        
        self.setCentralWidget(widget)
        
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

worker_thread.py

from PySide6.QtCore import QThread, Signal
import time
import threading

class WorkerThread(QThread):
    update_progress = Signal(str)
    
    def run(self):
        
        count = 0
        while count < 10000:            
            count += 1
            print(f'worker: {count}')
            self.update_progress.emit(f'{count}')
            print(f'worker thread: {threading.current_thread()}')
            time.sleep(1)

run_worker_thread.py

from PySide6.QtWidgets import QWidget, QHBoxLayout, QPushButton
from worker_thread import WorkerThread
from return_message_label import ReturnMessage

class RunWorkerThread(QWidget):
    
    def __init__(self):
        super(RunWorkerThread, self).__init__()
        
        self.rm = ReturnMessage()
        self.worker = WorkerThread()
        
        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setSpacing(20)
        
        btn = QPushButton('Process Data')
        btn.clicked.connect(self.processData)
        self.layout.addWidget(btn)
        
        self.setLayout(self.layout)
        
    def processData(self):
        self.worker.start()
        self.worker.update_progress.connect(self.rm.message_updater)

返回消息标签.py

from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
from PySide6.QtCore import Slot
import threading

class ReturnMessage(QWidget):
    
    def __init__(self):        
        super(ReturnMessage, self).__init__()

        self.initUI()

    def initUI(self):
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setSpacing(10)
        
        self.label1 = QLabel("python")
        
        self.layout.addWidget(self.label1)
        
        self.setLayout(self.layout)
        
    @Slot(str)
    def message_updater(self, msg):
        
        print(f'return msg thread: {threading.current_thread()}')
        print(f'msg_updater: {msg}')
        self.label1.setText(f'{msg}')

我尝试使用以下方法更新 GUI:repaint()、update()、QApplication.ProcessEvents()。这些都不起作用

python pyqt pyside qthread
1个回答
0
投票

特别感谢@musicamante带领我走上了写作之路。以下是解决困境的方法:

main.py:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QPushButton
from PySide6.QtCore import Slot
from return_message_label import ReturnMessage
from worker_thread import WorkerThread

class MainWindow(QMainWindow):
    
    def __init__(self):
        super().__init__() 
        
        self.worker = WorkerThread()
        self.rm = ReturnMessage()
        
        self.setWindowTitle("Title")
        self.setMinimumSize(800, 400)        
        self.layout = QVBoxLayout()
        
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setSpacing(20)
        
        self.btn = QPushButton('Process Data')
        self.btn.clicked.connect(self.processData)
        self.layout.addWidget(self.btn)
        
        self.layout.addWidget(self.rm)
            
        widget = QWidget()
        widget.setLayout(self.layout)
        
        self.setCentralWidget(widget)
        
    def processData(self):
        self.worker.start()
        self.worker.update_progress.connect(self.rm.message_updater)
        
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

worker_thread.py:

from PySide6.QtCore import QThread, Signal
import time
import threading

class WorkerThread(QThread):
    update_progress = Signal(str)
    
    def run(self):
        
        count = 0
        while count < 10000:            
            count += 1
            print(f'worker: {count}')
            self.update_progress.emit(f'{count}')
            print(f'worker thread: {threading.current_thread()}')
            time.sleep(1)

return_message_label.py:

from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
from PySide6.QtCore import Slot
import threading

class ReturnMessage(QWidget):
    
    def __init__(self):        
        super(ReturnMessage, self).__init__()

        self.initUI()

    def initUI(self):
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setSpacing(10)
        
        self.label1 = QLabel("python")
        
        self.layout.addWidget(self.label1)
        
        self.setLayout(self.layout)
        
    @Slot(str)
    def message_updater(self, msg):
        
        print(f'return msg thread: {threading.current_thread()}')
        print(f'msg_updater: {msg}')
        self.label1.setText(f'{msg}')
© www.soinside.com 2019 - 2024. All rights reserved.