language - python qt5 tutorial



PyQt4 Aguarde na discussão por entrada do usuário da GUI (1)

Por padrão, um QThread possui um loop de eventos que pode processar sinais e slots. Em sua implementação atual, infelizmente, você removeu esse comportamento substituindo QThread.run . Se você restaurá-lo, você pode obter o comportamento desejado.

Então, se você não pode substituir o QThread.run() , como você faz o threading no Qt? Uma abordagem alternativa ao encadeamento é colocar seu código em uma subclasse de QObject e mover esse objeto para uma instância QThread padrão. Você pode então conectar sinais e slots juntos entre o thread principal e o QThread para se comunicar em ambas as direções. Isso permitirá que você implemente o comportamento desejado.

No exemplo abaixo, iniciei um thread de trabalho que imprime no terminal, aguarda 2 segundos, imprime novamente e aguarda a entrada do usuário. Quando o botão é clicado, uma segunda função separada no thread de trabalho é executada e imprime no terminal no mesmo padrão da primeira vez. Por favor, note a ordem em que eu uso moveToThread() e conecte os sinais (de acordo com this ).

Código:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time

class MyWorker(QObject):

    wait_for_input = pyqtSignal()
    done = pyqtSignal()


    @pyqtSlot()
    def firstWork(self):
        print 'doing first work'
        time.sleep(2)
        print 'first work done'
        self.wait_for_input.emit()

    @pyqtSlot()
    def secondWork(self):
        print 'doing second work'
        time.sleep(2)
        print 'second work done'
        self.done.emit()


class Window(QWidget):
    def __init__(self, parent = None):
        super(Window, self).__init__()

        self.initUi()
        self.setupThread()

    def initUi(self):
        layout = QVBoxLayout()
        self.button = QPushButton('User input')
        self.button.setEnabled(False)
        layout.addWidget(self.button)
        self.setLayout(layout)
        self.show()

    @pyqtSlot()
    def enableButton(self):
        self.button.setEnabled(True)

    @pyqtSlot()    
    def done(self):
        self.button.setEnabled(False)

    def setupThread(self):
        self.thread = QThread()
        self.worker = MyWorker()

        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.firstWork)
        self.button.clicked.connect(self.worker.secondWork)
        self.worker.wait_for_input.connect(self.enableButton)
        self.worker.done.connect(self.done)

        # Start thread
        self.thread.start()    

if __name__ == "__main__":
    app = QApplication([])
    w = Window()
    app.exec_()

https://ffff65535.com

Eu tenho uma classe de thread "MyThread" e meu aplicativo principal que é simplesmente chamado de "Gui". Eu quero criar alguns objetos da classe de segmento, mas para este exemplo eu criei apenas um objeto. A classe thread faz algum trabalho, em seguida, emite um sinal para a classe Gui, indicando que uma entrada do usuário é necessária (essa indicação, por enquanto, é simplesmente alterar o texto de um botão). Em seguida, o segmento deve aguardar uma entrada do usuário (nesse caso, um clique no botão) e, em seguida, continuar fazendo o que está fazendo ...

from PyQt4 import QtGui, QtCore
class MyTrhead(QtCore.QThread):
    trigger = QtCore.pyqtSignal(str)

    def run(self):
        print(self.currentThreadId())
        for i in range(0,10):
            print("working ")
            self.trigger.emit("3 + {} = ?".format(i))
            #### WAIT FOR RESULT
            time.sleep(1)


class Gui(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Gui, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.btn)

        self.t1 = MyTrhead()
        self.t1.trigger.connect(self.dispaly_message)
        self.t1.start()
        print("thread: {}".format(self.t1.isRunning()))


    @QtCore.pyqtSlot(str)
    def dispaly_message(self, mystr):
        self.pushButton.setText(mystr)

    def btn(self):
        print("Return result to corresponding thread")



if "__main__" == __name__:
    import sys
    app = QtGui.QApplication(sys.argv)
    m = Gui()
    m.show()
    sys.exit(app.exec_())

Como posso esperar em (múltiplos) threads por uma entrada do usuário?





pyqt4