[PyQt] how to set up a timer to call a method after a delay?

Steve Castellotti sc at puzzlebox.info
Thu Jul 1 09:37:00 BST 2010


On Thu, 2010-07-01 at 09:09 +0100, Phil Thompson wrote: 
> >     I'm still getting this error:
> > 
> > QObject::startTimer: QTimer can only be used with threads started with
> > QThread
> 
> I think that is a misleading message - you need to provide a test case.
> 
> Because Qt sockets are handled with the event loop you usually do not need
> to use threads to handle multiple connections.


Thanks again for the replies.


I've got my server (and test client) working to the point where it
handles multiple connections and disconnections, though there is still
some cleanup work left around things like timeouts.


I'm not 100% certain I'm doing everything "right" but here's roughly how
it looks now (translated to pseudo code):


class server:
  def __init__(self, parent=None):
    self.connections = []
    self.packet_queue = []
    self.socket = QtNetwork.QTcpServer()
    self.socket.newConnection.connect(self.processConnection)
    self.updateTimer = QtCore.QTimer()
    QtCore.QObject.connect(self.updateTimer, QtCore.SIGNAL("timeout()"),
self.timerEvent)
    self.updateTimer.start(1000)


  def processConnection(self):
     client = self.socket.nextPendingConnection()
     client.disconnected.connect(self.deleteDisconnected)
     self.connections.append(client)


  def deleteDisconnected(self):
     index = 0
     for connection in self.connections:
       state = connection.state()
       if ((state != QtNetwork.QAbstractSocket.ConnectingState) and \
           (state != QtNetwork.QAbstractSocket.ConnectedState)):
         connection.deleteLater()
         del(self.connections[index]
       index += 1


  def timerEvent(self):
    if self.connections != []:
      self.updateStatus()
      self.sendPacketQueue()


  def sendPacketQueue(self):
    while (len(self.packet_queue) > 0):
      packet = self.packet_queue[0]
      del self.packet_queue[0]
      index = 0
      for connection in self.connections:
        state = connection.state()
        if state == QtNetwork.QAbstractSocket.ConnectedState:
          self.sendResponse(connection, packet)
        index += 1



... where "sendResponse" handles the actual data preparation for
transmission and writing to the connected socket, and "updateStatus"
appends packets of data to the packet_queue.


I'm not sure if its wise to delete all connections which aren't either
in a Connected or Connecting state when any single one disconnects, but
otherwise I couldn't figure out how to track connections and make sure
all references to a disconnecting client were deleted. For example if I
just attached "deleteLater" directly to the client.disconnect signal,
the reference would remain in the self.connections list and next time
the timer came around to call sendPacketQueue I would get a segfault.


For the moment it seems to be behaving well but I would be curious to
know if there's a smarter way to handle managing multiple connected
clients.



Cheers

Steve Castellotti





More information about the PyQt mailing list