PyQt: окно перестает отвечать при прослушивании IP-порта

Я пытаюсь создать простое приложение для чата с сокетами. Когда я пробовал что-то простое, создавая цикл и прослушивая мое имя хоста и порт, GUI начинал зависать и вообще не отвечал.

Тем не менее, я также попробовал QTimer(), так как он разработан для PyQt, но он принесет тот же результат и заморозит окно.

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 секунд (когда происходит тайм-аут), начинает зависать окно, в чем может быть проблема? мне нужно разделить процессы? Есть ли другое лучшее решение для этого?

2 ответа

Решение

Вам нужно сделать GUI и связь в разных потоках. Когда сокет, например, ожидает некоторые данные, графический интерфейс пользователя блокируется. Вы можете соединить два потока, используя сигнал / слоты QT.

Например, Пример - это класс для GUI. 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()

Дополнительные документы по Сигналу / Слотам http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

Примечание. В приведенном выше примере вам потребуется функция MyThread.process, чтобы завершить работу перед выходом из приложения. Это можно сделать, повернув переменную should_continue в false

Скорее всего, проблема возникает потому, что вы подключаете сокет только в основном приложении, которое останавливает весь процесс, включая графический интерфейс. Таким образом, решение лучше использовать функцию сокета и функцию чата в отдельном процессе, используя модуль подпроцесса и модуль многопроцессорной обработки.

Используя их, вы будете запускать приложение sockect в другом процессе, кроме основного процесса графического интерфейса, и оба будут работать параллельно, не останавливая основное приложение.

Другие вопросы по тегам