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 в другом процессе, кроме основного процесса графического интерфейса, и оба будут работать параллельно, не останавливая основное приложение.