tutorial pyqtsignal python pyqt signals-slots

pyqtsignal - Emitir señal en el hilo de python estándar



qt designer python (1)

Tengo una aplicación enhebrada donde tengo un hilo de red. La parte UI pasa una callback de callback a este hilo. El hilo es un hilo de python normal , no es QThread .

¿Es posible emitir PyQT Slot dentro de este hilo?


No, no es posible emitir una señal PyQt desde un hilo de Python como este.

Sin embargo, una posible solución es usar un objeto adicional compartido por ambos hilos, realizando las operaciones necesarias para finalmente emitir una señal PyQt segura para hilos.

Aquí hay una implementación de una clase "SafeConnector", haciendo uso de un par de sockets conectados y una cola para intercambiar datos entre los dos hilos, y usando un QSocketNotifier para volver al bucle de Qt. Un QObject se usa para hacer posible emitir una señal Qt adecuada:

from PyQt4 import Qt, QtCore, QtGui import threading import socket import Queue import time # Object of this class has to be shared between # the two threads (Python and Qt one). # Qt thread calls ''connect'', # Python thread calls ''emit''. # The slot corresponding to the emitted signal # will be called in Qt''s thread. class SafeConnector: def __init__(self): self._rsock, self._wsock = socket.socketpair() self._queue = Queue.Queue() self._qt_object = QtCore.QObject() self._notifier = QtCore.QSocketNotifier(self._rsock.fileno(), QtCore.QSocketNotifier.Read) self._notifier.activated.connect(self._recv) def connect(self, signal, receiver): QtCore.QObject.connect(self._qt_object, signal, receiver) # should be called by Python thread def emit(self, signal, args): self._queue.put((signal, args)) self._wsock.send(''!'') # happens in Qt''s main thread def _recv(self): self._rsock.recv(1) signal, args = self._queue.get() self._qt_object.emit(signal, args) class PythonThread(threading.Thread): def __init__(self, connector, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) self.connector = connector self.daemon = True def emit_signal(self): self.connector.emit(QtCore.SIGNAL("test"), str(time.time())) def run(self): while True: time.sleep(1) self.emit_signal() if __name__ == ''__main__'': app = QtGui.QApplication([]) mainwin = QtGui.QMainWindow() label = QtGui.QLabel(mainwin) mainwin.setCentralWidget(label) connector = SafeConnector() python_thread = PythonThread(connector) connector.connect(QtCore.SIGNAL("test"), label.setText) python_thread.start() mainwin.show() app.exec_()