2

TCP サーバー用のシンプルな UI を開発しており、サーバーから送信されたログ メッセージで UI を更新する必要がありますが、問題は、そのサーバーへの接続が別のスレッドにあるため、直接触れることができないことです。 UI のウィジェット (再入可能ではないため)。

このテーマに関する記事をいくつか読み、最もエレガントな (そして簡単な) 方法と思われるシグナルを選択しました。

私は次のことをしました:

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))

そしてサーバークラスでは:

class MainServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    trigger = QtCore.pyqtSignal(str)

    def printLog(self, message):
        print message
        self.trigger.emit(message)

しかし、アプリを実行すると、次のエラー メッセージが表示されます。

TypeError: pyqtSignal must be bound to a QObject, not 'instance'

別のスレッド (およびクラス) から UI を更新する他の (簡単な) 方法がある場合、またはこのエラーを修正する方法を知っている場合は、お知らせください。

4

2 に答える 2

3

それはほとんどこれです:

class Signals(QObject):
    trigger = pyqtSignal(str)

で使用するにはMainServer:

class MainServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
   def __init__(self, parent=None):
       self.signals = Signals()
       self.signals.trigger.emit("triggered")
于 2012-12-23T22:00:05.460 に答える
1

QObject私のサーバークラスに含まれる(クラスの)ミディアムオブジェクトを使用して解決しました:

class Logger(QtCore.QObject):

    trigger = QtCore.pyqtSignal(str)
    def __init__(self):
        super(Logger,self).__init__()
    def send(self, string):
        self.trigger.emit(string)
于 2012-12-04T21:10:35.917 に答える