在QThread中运行QApplication时得到神秘警告

时间:2019-04-18 12:31:07

标签: python python-3.x qt pyqt pyqt5

我正在尝试编写一个可以包装在所有可迭代对象上的类,并且该类在进行迭代时显示一个QT进度条,指示程序在循环中走了多远。

为了不阻塞主线程(应该是主线程,因为这是用户在包装类上进行迭代的地方),所以我在辅助线程中运行QApplication,尽管一切正常基本上像预期的那样,我收到了一些我不太了解的神秘警告。

任何人都知道出了什么问题吗?

我在其中放置了一些打印语句,以突出显示警告的确切位置。我收到2个'QObject :: setParent:无法设置父级,新父级处于不同线程中”警告,在调用QApplication.show()之后立即得到,然后在每次调用QProgressBar.setValue( )。

我对此一无所知。

from __future__ import annotations

import time
from typing import Any

from PyQt5 import QtWidgets as Qwidgets
from PyQt5 import QtCore as Qcore


class ProgressBar(Qcore.QObject):
    signal_tick, signal_done = Qcore.pyqtSignal(), Qcore.pyqtSignal()

    def __init__(self, iterable, name: str = None, text: str = None) -> None:
        super().__init__()

        self.iterable, self.thread = iterable, Qcore.QThread()

        self.app = ProgressBarApp(length=len(iterable))
        self.app.moveToThread(self.thread)

        self.signal_tick.connect(self.app.on_progress_tick)
        self.signal_done.connect(self.app.end_loop)

        self.thread.started.connect(self.app.start_loop)

    def __iter__(self) -> ProgressBar:
        self.__iter = iter(self.iterable)
        self.thread.start()
        time.sleep(1)
        return self

    def __next__(self) -> Any:
        self.signal_tick.emit()
        try:
            return next(self.__iter)
        except StopIteration:
            self.signal_done.emit()
            self.thread.quit()
            self.thread.wait()
            raise StopIteration


class ProgressBarApp(Qwidgets.QApplication):
    def __init__(self, length: int) -> None:
        super().__init__([])

        self.window, self.count = Qwidgets.QMainWindow(), 0

        self.bar = Qwidgets.QProgressBar(parent=self.window)
        self.bar.setRange(0, length)

        self.window.setCentralWidget(self.bar)

    @Qcore.pyqtSlot()
    def on_progress_tick(self) -> None:
        print("Before updating the progressbar.")
        self.bar.setValue(self.count)
        print("After updating the progressbar.")
        self.count += 1

    @Qcore.pyqtSlot()
    def start_loop(self) -> None:
        print("Before showing the main window.")
        self.window.show()
        print("After showing the main window.")
        self.exec()

    @Qcore.pyqtSlot()
    def end_loop(self) -> None:
        self.window.hide()
        self.quit()


if __name__ == '__main__':
    for _ in ProgressBar(range(10)):
        time.sleep(1)

0 个答案:

没有答案