PyQt:Window 监听 ip、端口时停止响应

PyQt: Window stops responding when listening to ip, port

我正在尝试用套接字制作一个简单的聊天应用程序,当我尝试一个简单的事情时,循环并监听我的主机名和端口,GUI 将开始冻结并且根本不会响应。

然而,我也尝试了 QTimer(),因为它是为 PyQt 设计的,但它会带来相同的结果并冻结 window。

def startloop(self):
    IP = socket.gethostbyname(socket.gethostname())
    self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.s.bind((IP, 5005))
    self.loop = QtCore.QTimer(self)
    self.loop.timeout.connect(self.check)
    self.loop.start(10000)

def recv(self):
    data, addr = self.s.data.recvfrom(1024)
    print data

每隔 10 秒(发生超时时),它开始冻结 window,可能是什么问题?我需要分开进程吗?还有其他更好的解决方案吗?

问题的发生很可能是因为您仅在主应用程序中连接套接字,这会拖延包括 GUI 在内的整个过程。 所以解决方案最好是 运行 套接字功能和聊天功能在单独的进程中使用 subprocess module and multiprocessing 模块。

通过使用这些,您将 运行在不同的进程中运行 sockect 应用程序,除了主 GUI 进程,并且两者将并行工作而不会停止主应用程序

您需要在不同的线程中进行 GUI 和通信。例如,当套接字正在等待某些数据时,GUI 会被阻塞。您可以使用 QT 的 signal/slots 连接两个线程。

例如,示例是 GUI 的 class。 MyThread 会在另一个线程中 运行 每隔几秒钟调用一个 Example 槽。 导入系统 从 PyQt4 导入 QtGui,QtCore 导入时间 导入线程

class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()
        QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
        btn = QtGui.QPushButton('Button', self)
        self.show()
        self.background = MyThread(self)
        t = threading.Thread(target=self.background.process)
        t.start()
        self.background.notify.connect(self.notify)

    @QtCore.pyqtSlot()
    def notify(self):
        print("I have been notified")

class MyThread(QtCore.QObject):

    notify = QtCore.pyqtSignal()

    def __init__(self, parent):
        super(MyThread, self).__init__(parent)
        self.should_continue = True

    def process(self):
        while self.should_continue:
            # Here, do your server stuff.
            time.sleep(1)
            self.notify.emit()

def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

关于 Signal/Slots http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

的更多文档

注意 在上面的示例中,您需要 MyThread.process 函数在退出应用程序之前完成。这可以通过将 should_continue 变量设置为 false

来完成