私はPyQt4を使用して最初のGUIアプリケーションを作成している最中で、非常に基本的な質問に出くわしましたが、良い答えが見つからないようです。
スレッドを使用して、メインウィンドウをブロックせずに繰り返しタスクを継続的に実行しています。スレッドには、メインウィンドウからの情報(スピンボックスの現在の値など)が必要です。これらの情報は、スレッドの実行中にも変更される可能性があります。この状況で、メインウィンドウとスレッドの間でそのようなデータを共有する適切な方法は何ですか?
素朴に、私は次の可能性を思い付くことができました:
3つのオプションはすべて私の特定のユースケースで機能する可能性が高いですが(2つは少し複雑ですが)、より良い/よりPythonic /よりQtのような方法があるはずだと感じています。
これは私がやりたいことを説明する最小限の作業例です。この場合はオプション1を使用します。
from PyQt4 import QtGui, QtCore
import time, sys
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
self.spinbox = QtGui.QSpinBox(self)
self.spinbox.setValue(1)
self.layout.addWidget(self.spinbox)
self.output = QtGui.QLCDNumber(self)
self.layout.addWidget(self.output)
self.worker = Worker(self)
self.connect(self.worker, QtCore.SIGNAL('beep'), self.update)
self.worker.start()
def update(self, number):
self.output.display(number)
class Worker(QtCore.QThread):
def __init__(self, host_window):
super(Worker, self).__init__()
self.host = host_window
self.running = False
def run(self):
self.running = True
i = 0
while self.running:
i += 1
self.emit(QtCore.SIGNAL('beep'), i)
sleep_time = self.host.spinbox.value()
time.sleep(sleep_time)
def stop(self):
self.running = False
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
PS:私はPyQtにまったく慣れていないので、コードに他の問題があるか、質問が不明確である可能性は低いとは言えません。この場合、質問にコメントまたは編集してください。
ウィジェットはスレッドセーフではありません。スレッドとQObjectを参照してください。
QObjectは再入可能ですが、GUIクラス、特にQWidgetとそのすべてのサブクラスは再入可能ではありません。メインスレッドからのみ使用できます。
そして、ここでより多くの定義を参照してください:再入可能性とスレッドセーフ
メインスレッドではウィジェットのみを使用し、シグナルとスロットを使用して他のスレッドと通信する必要があります。
グローバル変数が機能するとは思いませんが、正直なところ理由はわかりません。
この例でシグナルを使用する方法:
#in main
self.worker = Worker(self.spinbox.value())
self.worker.beep.connect(self.update)
self.spinbox.valueChanged.connect(self.worker.update_value)
class Worker(QtCore.QThread):
beep=QtCore.pyqtSignal(int)
def __init__(self,sleep_time):
super(Worker, self).__init__()
self.running = False
self.sleep_time=sleep_time
def run(self):
self.running = True
i = 0
while self.running:
i += 1
self.beep.emit(i)
time.sleep(self.sleep_time)
def stop(self):
self.running = False
def update_value(self,value):
self.sleep_time=value
注意:新しいスタイルの信号とスロットを使用しています
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加