I’m developping a simple UI for a TCP Server, and need to update the UI with log messages sent from the server, but the problem is that any connection to that server is in a separate thread, so I can’t touch directly the UI’s widgets (as they are not reentrant).
I’ve read some articles on the subject and chose what seems like the most elegant (and easy) way to do it: signals.
I’ve done the following :
class Ui_Dialog(QtCore.QObject):
def __init__(self):
super(QtCore.QObject, self).__init__()
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(800, 580)
self.serverLog = QtGui.QTextEdit(Dialog)
self.serverLog.setGeometry(QtCore.QRect(0, 0, 800, 480))
self.serverLog.setObjectName(_fromUtf8("serverLog"))
#OTHER WIDGETS AND CODE DEFINED HERE
self.server = None
#SIGNALS
self.clearLogButton.clicked.connect(self.serverLog.clear)
self.stopButton.clicked.connect(self.connectServer)
self.startButton.clicked.connect(self.connectServer)
def connectServer(self):
if (self.server is None):
host = str(self.ipEdit.text())
port = int(self.portEdit.text())
try:
self.server = server.MainServer((host, port), server.MyHTTPHandler)
self.server.setup(self)
self.printLog( "Hooray ! Server connected at {}:{}".format(host, port) )
# Start a thread with the server -- that thread will then start one more thread for each request
MainServer_thread = threading.Thread(target=self.server.serve_forever)
MainServer_thread.daemon = True
self.server.trigger.connect(QtCore.QObject(self.printLog))
MainServer_thread.start()
self.server.trigger.connect(self.printLog)
except errno.EADDRINUSE:
self.printLog("#ERROR: Address already in use. Try a different port.")
except errno.EADDRNOTAVAIL:
self.printLog("#ERROR: Address not available.")
def printLog(self, string):
self.serverLog.append(_fromUtf8(string))
And in the server class:
class MainServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
trigger = QtCore.pyqtSignal(str)
def printLog(self, message):
print message
self.trigger.emit(message)
But when I run my app, I get this message error :
TypeError: pyqtSignal must be bound to a QObject, not 'instance'
If there’s any other (easy) way to update the UI from another thread (and class) or you know how to fix this error, please let me know !
Just solved it using a medium object (of class
QObject) contained in my server class: