2

PyQt GUIを使用するPythonアプリケーションがあります。このアプリケーションには、別のスレッドで実行したい I/O 操作がいくつかあります。スレッドが開始されると、アプリケーションのメイン ウィンドウのステータス バーにメッセージが書き込まれ、最後のスレッドが完了すると、ステータス バーのメッセージがクリアされます。QThread 経由でスレッド数を処理するにはどうすればよいですか?

コードの例を次に示します。

import sys, time
from PyQt4 import QtCore, QtGui
from functools import partial


def io_emulator(sleep_seconds):
    print 'We will sleep for %s seconds' % str(sleep_seconds)
    time.sleep(sleep_seconds)


class IOThread(QtCore.QThread):
    def __init__(self, func):
        QtCore.QThread.__init__(self)
        self.io_func = func

    def run(self):
        self.io_func()


class m_Window(QtGui.QWidget):
    def __init__(self):
        super(m_Window, self).__init__()

        self.initUI()

    def initUI(self):
        self.thread_button = QtGui.QPushButton("Thread", self)
        self.thread_button.move(30, 10)
        self.spinbox = QtGui.QSpinBox(self)
        self.spinbox.move(30, 50)
        self.stat_label = QtGui.QLabel("", self)
        self.stat_label.setGeometry(QtCore.QRect(200, 200, 150, 14))
        self.stat_label.move(30,90)

        self.setWindowTitle('Threads')
        self.show()

        self.thread_button.clicked.connect(self._sleeper)

    def _sleeper(self):
        seconds = int(self.spinbox.text())
        stat_str = 'Sleeping %s seconds' % str(seconds)

        io_func = partial(io_emulator, seconds)
        set_status_f = partial(self.set_status_msg, stat_str)

        self.thread =  IOThread(io_func)
        self.thread.started.connect(set_status_f)
        self.thread.finished.connect(self.clear_status_msg)

        self.thread.start()

    def set_status_msg(self, msg):
        self.stat_label.setText(msg)

    def clear_status_msg(self):
        self.stat_label.clear()


def main():
    app = QtGui.QApplication(sys.argv)
    m = m_Window()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

そのメッセージは、最後のスレッドが終了したときにのみクリアされます。

4

1 に答える 1

1

メインスレッド以外のスレッドからQWidget関数を呼び出すことはできません。別のスレッドでGUI操作をトリガーする場合は、メインスレッドに接続されているシグナルを発行して通信する必要があります。

def someFunc():
    return "message"

class IOThread(QtCore.QThread):

    statusUpdate = QtCore.pyqtSignal(str)

    def __init__(self, func):
        QtCore.QThread.__init__(self)
        self.io_func = func

    def run(self):
        msg = self.io_func()
        self.statusUpdate.emit(msg)

次に、メインスレッドで、ioスレッドをステータスラベルまたは中間ハンドラーに接続します。

io_thread = IOThread(someFunc)
io_thread.statusUpdate.connect(self.status_label.setText)

これにより、キューに入れられた接続が作成され、実行のために呼び出しがメインスレッドのイベントループに配置されます。

于 2013-01-07T17:06:40.863 に答える