基于QRunnable的PyQt多线程程序工作不正常

2024-09-21 01:17:11 发布

您现在位置:Python中文网/ 问答频道 /正文

在这个基于PyQt的小程序中,我创建了一个计数器,它在10秒内从0计数到10。虽然我使用QRunnable在一个单独的线程中运行countBox()中的计数器,但在按下开始按钮后,GUI没有响应,计数器根本不工作。你知道这有什么问题吗?谢谢

from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QLabel
from PyQt5.QtCore import Qt, QRunnable, pyqtSlot, QThreadPool

import time, sys

class Worker(QRunnable):
    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):
        self.fn(*self.args, **self.kwargs)

def createCounterWorker():
    threadpool = QThreadPool()
    worker = Worker(countBox)
    threadpool.start(worker)

def countBox():
    i = 0
    while i < 10:
        print(f'i: {i}')
        time.sleep(1.0)
        i += 1

class Counter():
    def __init__(self, layout):
        self.startButton = QPushButton(f'Start')
        self.startButton.pressed.connect(lambda: createCounterWorker())
        layout.addWidget(self.startButton)

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.layout = QVBoxLayout()

        self.btn = QPushButton('+')
        self.btn.pressed.connect(lambda: self.addNewCounter())
        self.layout.addWidget(self.btn)

        w = QWidget()
        w.setLayout(self.layout)
        self.setCentralWidget(w)
        self.show()

    def addNewCounter(self):
        newCount = Counter(self.layout)

app = QApplication([])
window = MainWindow()

sys.exit(app.exec_())

Tags: fromimportselfinitdef计数器argspyqt5
1条回答
网友
1楼 · 发布于 2024-09-21 01:17:11

问题很简单:threadpool是创建线程的对象,它是一个局部变量,将随线程一起立即销毁,因此countBox将在主线程中执行,导致GUI冻结,因此解决方案是延长该变量的生命周期,因此有以下选项:

  • 使threadpool成为全局变量:

    threadpool = QThreadPool()
    
    def createCounterWorker():
        worker = Worker(countBox)
        threadpool.start(worker)
  • 使用QThreadPool.globalInstance():

    def createCounterWorker():
        worker = Worker(countBox)
        QThreadPool.globalInstance().start(worker)

相关问题 更多 >

    热门问题