#やりたいこと
サブスレッドの終了を通知で知りたい
#問題
以下コードではサブスレッド終了条件を"A"が押されたらにしています。(class Worker部分)
サブスレッド終了時にQMessage boxで通知終了を知らせたいのですがエラーがでてしまいました。
<エラーメッセージ>
QObject::setParent: Cannot set parent, new parent is in a different thread
サブスレッドでは呼び出せない模様
python
1import sys 2import logging 3import time 4import signal 5from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot, QTimer,Qt 6from PyQt5.QtWidgets import ( 7 QApplication, 8 QWidget, 9 QLineEdit, 10 QPlainTextEdit, 11 QPushButton, 12 QGridLayout, 13 QShortcut, 14 QAction, 15 QMessageBox, 16 ) 17from PyQt5.QtGui import QKeySequence 18from PyQt5 import QtGui 19FLAG = False 20class Worker(QObject): 21 22 done = pyqtSignal(str) 23 24 @pyqtSlot(str) 25 def execute(self, text): 26 global FLAG 27 FLAG = False 28 # シグナル経由で呼び出すと別スレッドで実行されますが、 29 # シグナル&スロット機構を使う場合は、イベントループを使う必要があり、 30 # スレッドのイベントループを正常に稼働させるためには、 31 # 個々の関数(スロット)は即時に終了しなければなりません。 32 # 33 # 時間のかかる処理を行いたい場合は、 34 # 毎回新しいスレッドを生成するか、この中で更に別スレッドを使います。 35 36 while not FLAG: 37 print("Waiting for signal...") 38 QMessageBox.information(None, "通知", "Aが押されました。") 39 time.sleep(1) 40 41 42class View(QWidget): 43 44 sendMessage = pyqtSignal(str) 45 46 def __init__(self, parent=None): 47 super().__init__(parent) 48 lineEdit = QLineEdit(self) 49 button = QPushButton("Execute", self) 50 textEdit = QPlainTextEdit(self) 51 52 lineEdit.returnPressed.connect(self._onClicked) 53 button.clicked.connect(self._onClicked) 54 55 layout = QGridLayout(self) 56 layout.addWidget(lineEdit, 0, 0) 57 layout.addWidget(button, 0, 1) 58 layout.addWidget(textEdit, 1, 0, 1, 2) 59 60 self._button = button 61 self._textEdit = textEdit 62 self._lineEdit = lineEdit 63 64 def _onClicked(self): 65 text = self._lineEdit.text() 66 self.sendMessage.emit(text) 67 self._lineEdit.clear() 68 69 @pyqtSlot(str) 70 def addResultText(self, text): 71 global FLAG 72 logging.info("addResultText: %s", text) 73 self._textEdit.appendPlainText(text) 74 FLAG = True 75 76def onControlC(): 77 global FLAG 78 print("A pressed") 79 FLAG = True 80 81 82def main(): 83 84 app = QApplication(sys.argv) 85 view = View() 86 87 # スレッド開始 88 thread = QThread(app) 89 worker = Worker() 90 worker.moveToThread(thread) 91 thread.start() 92 93 # view: メインスレッド, worker: 別スレッド 94 view.sendMessage.connect(worker.execute) 95 worker.done.connect(view.addResultText) 96 97 98 99 action = QAction(view) 100 action.setShortcut(QKeySequence('A')) 101 action.triggered.connect(onControlC) 102 view.addAction(action) 103 104 # プログラム終了時にエラーが出ないように、スレッドの後始末 105 # ※ QThread の使い方によって後始末の方法が異なるので注意 106 # QThread.quit は、スレッドのイベントループを終了します。 107 app.aboutToQuit.connect(thread.quit) 108 109 view.show() 110 111 sys.exit(app.exec_()) 112 113 114if __name__ == '__main__': 115 logging.basicConfig( 116 level=logging.DEBUG, 117 # ログにスレッド名を表示するための書式設定 118 # 119 # ※ 制限: QThread のスレッド名は Dummy-1 のように表示されますが、 120 # 今回は、メインスレッドかそうでないかを区別できれば充分です。 121 format="[%(threadName)-10s][%(levelname)-8s] %(message)s", 122 ) 123 main()
#質問
サブスレッド終了通知を知らせるための他の良い方法はありますでしょうか
よろしくお願いいたします。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。