PyQt5 - 使用 QThread 更新 Qtablewidget

PyQt5 - update Qtablewidget with QThread

谁能帮帮我,应用程序崩溃了。

我已经完成研究并发现 下面是我的代码:

from PyQt5.QtCore import QThread, pyqtSignal
import threading
import time

class Job(QThread):
    data_downloaded = pyqtSignal(str)

    def __init__(self, url):
        QThread.__init__(self)
        # self.__flag = threading.Event()
        # self.__flag.set()
        # self.__running = threading.Event()
        # self.__running.set()


    def run(self):
        for i in range(100):
            self.data_downloaded.emit("B")  # 朝connect的函数发射一个进度信号
            time.sleep(1)

    # def pause(self):
    #     self.__flag.clear()     # 设置为False, 让线程阻塞
    #
    # def resume(self):
    #     self.__flag.set()    # 设置为True, 让线程停止阻塞
    #
    # def stop(self):
    #     self.__flag.set()       # 将线程从暂停状态恢复, 如何已经暂停的话
    #     self.__running.clear()        # 设置为False

主要window:

from xxx import Job 
class SearchWindow(QWidget):
    ......
    ...... # There's a QTableWidget on main window, after right clicked "Start Download", Job will be created 
    ......

    def right_click_from_download_list_context(self):
        row_num = []
        for i in self.download_list.selectionModel().selection().indexes():
            row_num.append(i.row())
        popMenu = QMenu(self)
        self.start_download_action = QAction('Start Download', self)
        self.remove_task_action = QAction('删除此任务', self)
        self.start_download_action.triggered.connect(self.start_download)
        self.remove_task_action.triggered.connect(partial(self.remove_task, row_num))
        popMenu.addAction(self.start_download_action)
        popMenu.addAction(self.remove_task_action)
        popMenu.exec_(QCursor.pos())

    def start_download(self):
        print("AAAA")
        downloader = Job("http://www.baidu.com")
        print("BBB")
        downloader.data_downloaded.connect(self.update_download_process)
        print("ccc")
        downloader.start()
        print("ddd")

    @pyqtSlot(str)
    def update_download_process(self, data_process):
        print(data_process)

调试了一下,"AAAA"、"BBB"、"ccc"、"ddd"都可以成功打印出来,估计是我的Job出错了QThread.

谁能帮我一个忙,我只是找不到哪里可能出错。提前致谢:)

问题是因为在函数内创建的变量只在函数执行时存在,并且downloader的消除也会消除线程。为此,有 2 个解决方案:

  • 创建 class 的 downloader 成员:

def start_download(self):
    print("AAAA")
    self.downloader = Job("http://www.baidu.com")
    print("BBB")
    self.downloader.data_downloaded.connect(self.update_download_process)
    print("ccc")
    self.downloader.start()
    print("ddd")
  • 将父项传递给作业:

class Job(QThread):
    data_downloaded = pyqtSignal(str)

    def __init__(self, url, parent=None):
        QThread.__init__(self, parent)

    [...]


class SearchWindow(QWidget):
    [...]
    def start_download(self):
        print("AAAA")
        downloader = Job("http://www.baidu.com", self)
        print("BBB")
        downloader.data_downloaded.connect(self.update_download_process)
        print("ccc")
        downloader.start()
        print("ddd")