Fwd: Python Signal/Slot + QThred code analysis

Michael Torrie torriem at gmail.com
Thu Nov 27 23:52:14 CET 2014


On 11/27/2014 04:58 AM, Juan Christian wrote:
> What I have in mind is simple (I think), have the Outpost get the data
> using QThread, and when it got everything needed emit a signal. So when I
> have something like 'var = Outpost('123')', when I get the signal I'll know
> that I can call 'var.trades, var.posts' and it won't give me NullErrors or
> something like that.

So there are a number of logic problems in your code.  The main one is
that the call to create your worker class returns immediately.  It's not
part of the thread itself.  So your signal logic will never work.

This was a good excuse for me to dive into Qt a bit more.  So it turns
out that QThread objects can have their own event loops. This turns out
to be quite ideal for what you want.  So here's a Worker class does
everything you want, but with only one instance, and uses signals properly:

class Worker(QThread):

    # This is the signal that we'll emit every time
    # we load a new set of values from the url
    new_value = Signal(str,str)

    def __init__(self, url, *args, **kwargs):
        super(Worker, self).__init__(*args, **kwargs)
        self.url = url
        self.start()

    def run(self):
        # Since we're going to run a mini event loop in the thread
        # we can create and use a timer here
        self.timer = QTimer()
        self.timer.start(5000)
        self.timer.timeout.connect(self.fetch_url)
        # Start the thread's event loop
        self.exec_()

    def fetch_url(self):
        # Doesn't matter how long this takes because it only
        # blocks the thread's event loop, not the GUI
        time.sleep(random.random() * 2)
        trades = str(random.random() * 25)
        posts = str(random.random() * 100)

        # communicate the values via the signal
        self.new_value.emit(trades, posts)

So with this, you can instantiate it once, then tie the new_value signal
to a callback in the main loop.  So no need for the Outlook object, and
no intermediate callbacks.  The thread signals directly.  And the
callback receives the data directly, so no check for NODATA values and
such:

def create_topic(trades, posts):
    box = QGroupBox()
    grid = QGridLayout()
    nickname = QTextEdit()

    box.setFixedHeight(200)
    nickname.setText("%s : %s" % (trades, posts))

    grid.addWidget(nickname)
    box.setLayout(grid)

    # Access global variable MainWindow, defined below
    MainWindow.vlay.addWidget(box)

Hope this helps.  Here's complete working code, minus the .ui file:
http://pastebin.com/VhmSFX2t





More information about the Python-list mailing list