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

Phil Thompson phil at riverbankcomputing.com
Thu Jul 1 09:55:17 BST 2010


On Thu, 01 Jul 2010 01:37:00 -0700, Steve Castellotti <sc at puzzlebox.info>
wrote:
> 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.

I don't see why you are using a timer at all - it can only slow things
down. Have you looked at the loopback.py example included with PyQt?

Phil


More information about the PyQt mailing list