2

I'm trying to make an app that receives UDP data and shows the data in a list view using python (PyQt5). When I start the receiver, the app gets stuck and does not respond. How can I fix this? See code below.

import sys
import os
import socket
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class udpReceiverApp():
     app = QApplication (sys.argv)
     x = 1
     ip = "192.168.1.4"
     port =515
     server_start = True
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     sock.bind((ip,port))

     def __init__(self):
         self.w = QWidget()
         self.lbl = QLabel ("udp receiver",self.w)
         self.btn = QPushButton ("click me",self.w)
         self.lst = QListWidget(self.w)
         self.lst.resize(200,100)

         self.lbl.move(10, 90)
         self.btn.move(50, 50)
         self.lst.move(10, 90)

         self.btn.clicked.connect(self.startReceiver)

         self.w.setGeometry(300, 300, 300, 200)
         self.w.setWindowTitle("udp receive")
         self.w.show()
         sys.exit(udpReceiverApp.app.exec_())

     def addLstItem(self):
         self.lst.insertItem(0,"item"+str(udpReceiverApp.x) )
         udpReceiverApp.x +=1

     def startReceiver(self):

         while udpReceiverApp.server_start:
               data, addr = self.sock.recvfrom(1024)
               self.lst.insertItem(0,data)

udpReceiverApp()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Your code hangs at ```data, addr = self.sock.recvfrom(1024)```. Solution here: https://stackoverflow.com/questions/2719017/how-to-set-timeout-on-pythons-socket-recv-method – Nic Laforge Mar 16 '19 at 03:36

1 Answers1

3

You should not have an infinite loop in the main thread since it locks the Qt event loop, instead you should execute it in another thread and send the information through signals

import sys
import os
import socket
from PyQt5 import QtCore, QtWidgets

class UDPWorker(QtCore.QObject):
    dataChanged = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(UDPWorker, self).__init__(parent)
        self.server_start = False

    @QtCore.pyqtSlot()
    def start(self):
        self.server_start = True
        ip = "192.168.1.4"
        port = 515
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind((ip,port))
        self.process()

    def process(self):
        while self.server_start:
            data, addr = self.sock.recvfrom(1024)
            self.dataChanged.emit(str(data))

class UDPWidget(QtWidgets.QWidget):
    started = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(UDPWidget, self).__init__(parent)
        btn = QtWidgets.QPushButton("Click Me")
        btn.clicked.connect(self.started)
        self.lst = QtWidgets.QListWidget()

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(QtWidgets.QLabel("udp receiver"))
        lay.addWidget(btn)
        lay.addWidget(self.lst)

        self.setWindowTitle("udp receive")

    @QtCore.pyqtSlot(str)
    def addItem(self, text):
        self.lst.insertItem(0, text)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = UDPWidget()
    worker = UDPWorker()
    thread = QtCore.QThread()
    thread.start()
    worker.moveToThread(thread)
    w.started.connect(worker.start)
    worker.dataChanged.connect(w.addItem)
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241