簡體   English   中英

主線程執行時不顯示進度指示器

[英]Progress Indicator is not shown while main thread executing

如何為 python 上的長處理線程創建加載警告?

我編輯了一些代碼參考上面的網站,在下面的部分有新的代碼:

import sys
import time
import _thread

from PyQt5.QtCore import QObject, pyqtSignal, Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QInputDialog, QApplication, QProgressDialog

class Message(QObject):
    finished = pyqtSignal()

def createAddress(password, name, obj):
    print('Count in child thread. 0 sec')
    time.sleep(1)
    print('Count in child thread. 1 sec')
    time.sleep(1)
    print('Count in child thread. 2 sec')
    time.sleep(1)
    print('Count in child thread. 3 sec')
    time.sleep(1)
    print('Count in child thread. 4 sec')
    time.sleep(1)
    obj.finished.emit()


class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        lay = QVBoxLayout(self)
        button = QPushButton("Start processing")
        lay.addWidget(button)
        button.clicked.connect(self.start_task)
        self.message_obj = Message()

    def start_task(self):
        password = "password"
        name, ok = QInputDialog.getText(None, 'Name the address', 'Enter the address name:')
        if ok:
            self.progress_indicator = QProgressDialog(self)
            self.progress_indicator.setWindowModality(Qt.WindowModal)
            self.progress_indicator.setRange(0, 0)
            self.progress_indicator.setAttribute(Qt.WA_DeleteOnClose)
            self.message_obj.finished.connect(self.progress_indicator.close, Qt.QueuedConnection)
            self.progress_indicator.show()
            _thread.start_new_thread(createAddress, (password, name, self.message_obj, ))
        print('Count in main thread. 0 sec')
        time.sleep(1)
        print('Count in main thread. 1 sec')
        time.sleep(1)
        print('Count in main thread. 2 sec')
        time.sleep(1)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.show()
    sys.exit(app.exec_())

單擊按鈕時,CMD 會正確打印 mainThread(start_task) 中的單詞和 subThread(createAddress) 中的單詞。 但是,直到 mainThread 完成計數,進度條才會顯示。

如何在 mainThread 執行時正確顯示進度條,謝謝。

您不應該在運行 GUI 的主線程中運行耗時的任務(如time.sleep() ),因為它會阻塞事件循環,因此另一種方法是在另一個線程中運行它,就像代碼的一部分一樣正在這樣做,但在其他地方它仍然在主線程中運行time.sleep()導致您看到的問題,所以首先您應該清楚:

  1. 如果您有消耗很少時間的周期性任務,那么您應該使用 QTimer。

  2. 如果周期性任務非常耗時,那么您應該在另一個線程中運行該任務。

在您的情況下,定期任務是打印,因此您必須使用選項 1

import sys
import time
import _thread

from PyQt5.QtCore import QObject, pyqtSignal, Qt, pyqtSlot, QTimer
from PyQt5.QtWidgets import (
    QWidget,
    QVBoxLayout,
    QPushButton,
    QInputDialog,
    QApplication,
    QProgressDialog,
)


class Message(QObject):
    finished = pyqtSignal()


def createAddress(password, name, obj):
    print("Count in child thread. 0 sec")
    time.sleep(1)
    print("Count in child thread. 1 sec")
    time.sleep(1)
    print("Count in child thread. 2 sec")
    time.sleep(1)
    print("Count in child thread. 3 sec")
    time.sleep(1)
    print("Count in child thread. 4 sec")
    time.sleep(1)
    obj.finished.emit()


class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        lay = QVBoxLayout(self)
        button = QPushButton("Start processing")
        lay.addWidget(button)
        button.clicked.connect(self.start_task)
        self.message_obj = Message()

        self.counter = 0
        self.timer = QTimer(interval=1000, timeout=self.on_timeout)

    def start_task(self):
        password = "password"
        name, ok = QInputDialog.getText(
            None, "Name the address", "Enter the address name:"
        )
        if ok:
            self.progress_indicator = QProgressDialog(self)
            self.progress_indicator.setWindowModality(Qt.WindowModal)
            self.progress_indicator.setRange(0, 0)
            self.progress_indicator.setAttribute(Qt.WA_DeleteOnClose)
            self.message_obj.finished.connect(
                self.progress_indicator.close, Qt.QueuedConnection
            )
            self.progress_indicator.show()
            _thread.start_new_thread(createAddress, (password, name, self.message_obj,))
            self.counter = 0
            self.timer.start()

    @pyqtSlot()
    def on_timeout(self):
        print("Count in main thread. {} sec".format(self.counter))
        self.counter += 1
        if self.counter > 3:
            self.timer.stop()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.show()
    sys.exit(app.exec_())

在調整threading庫並增加子進程的間隔時,您的代碼對我來說很好,因為進程欄需要時間才能出現。

import sys
import time

import threading
from PyQt5.QtCore import QObject, pyqtSignal, Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QInputDialog, QApplication, QProgressDialog

class Message(QObject):
    finished = pyqtSignal()

def createAddress(password, name, obj):
    print('Count in child thread. 0 sec')
    time.sleep(2)
    print('Count in child thread. 2 sec')
    time.sleep(2)
    print('Count in child thread. 4 sec')
    time.sleep(2)
    print('Count in child thread. 6 sec')
    time.sleep(2)
    print('Count in child thread. 8 sec')
    time.sleep(2)
    obj.finished.emit()


class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        lay = QVBoxLayout(self)
        button = QPushButton("Start processing")
        lay.addWidget(button)
        button.clicked.connect(self.start_task)
        self.message_obj = Message()

    def start_task(self):
        password = "password"
        name, ok = QInputDialog.getText(None, 'Name the address', 'Enter the address name:')
        if ok:

            self.progress_indicator = QProgressDialog(self)
            self.progress_indicator.setWindowModality(Qt.WindowModal)
            self.progress_indicator.setRange(0, 0)
            self.progress_indicator.setAttribute(Qt.WA_DeleteOnClose)
            self.message_obj.finished.connect(self.progress_indicator.close, Qt.QueuedConnection)
            self.progress_indicator.show()
            t1 = threading.Thread(target=createAddress, args=(password, name, self.message_obj))
            t1.start()

        print('Count in main thread. 0 sec')
        time.sleep(1)
        print('Count in main thread. 1 sec')
        time.sleep(1)
        print('Count in main thread. 2 sec')
        time.sleep(1)
        #t1.join()



if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.show()
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM