![](/img/trans.png)
[英]How to spawn child thread from main thread while main thread keeps executing in Python
[英]Progress Indicator is not shown while main thread executing
我編輯了一些代碼參考上面的網站,在下面的部分有新的代碼:
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()
導致您看到的問題,所以首先您應該清楚:
如果您有消耗很少時間的周期性任務,那么您應該使用 QTimer。
如果周期性任務非常耗時,那么您應該在另一個線程中運行該任務。
在您的情況下,定期任務是打印,因此您必須使用選項 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.