I want to provide another example of how I have used variable-length
arguments in PyQt, in hopes that perhaps someone can suggest a workaround or
another approach:

I have a class SignalProxy which is a subclass of QObject. The purpose of
SignalProxy is to catch rapidly repeated signals from one source, merge them
together into a single signal, and re-emit that signal. I use this in many
different places, but most commonly to catch valueChanged signals from a
QSpinBox, so that rolling the mouse wheel over the spin box only generates a
single signal at the end, rather than a rapid series of signals.  (I have
attached the code for this class for reference)

In PyQt (with old-style signals), this is trivial because when I emit a
signal, I do not need to know the name or signature of arguments that will
be passed through the signal until just before it is sent. Furthermore, I do
not need to select a particular signature when connecting a custom signal to
its slot; I simply connect it by name and _all_ signals with that name will
be connected, regardless of their argument signature.

This does not seem to be possible with PySide since I can not have arbitrary
signatures and I don't know any way to create new signals on the fly (at
least, none that would work in this example).

Any ideas? I like the syntax of these new-style signals, but so far I've
found them to be much more limited in their capabilties..

Luke



On Thu, Mar 3, 2011 at 19:12, Luke Campagnola <[email protected]>wrote:

> Hello,
> In my PyQt app, I frequently use variable-length argument lists with my
> signals, like this:
>     self.emit(QtCore.QObject.SIGNAL('signalName'), *args)
>
> Is there any way to accomplish the same thing in PySide using new-style
> signals?
>
> Thanks!
>
>
# -*- coding: utf-8 -*-
from PyQt4 import QtCore
from ptime import time

class SignalProxy(QtCore.QObject):
    """Object which collects rapid-fire signals and condenses them
    into a single signal. Used, for example, to prevent a SpinBox
    from generating multiple signals when the mouse wheel is rolled
    over it."""
    
    def __init__(self, source, signal, delay=0.3):
        """Initialization arguments:
        source - Any QObject that will emit signal
        signal - Output of QtCore.SIGNAL(...)
        delay - Time (in seconds) to wait for signals to stop before emitting (default 0.3s)"""
        
        QtCore.QObject.__init__(self)
        source.connect(source, signal, self.signalReceived)
        self.delay = delay
        self.args = None
        self.signal = signal
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.flush)
        self.block = False
        
    def setDelay(self, delay):
        self.delay = delay
        
    def signalReceived(self, *args):
        """Received signal. Cancel previous timer and store args to be forwarded later."""
        if self.block:
            return
        self.args = args
        self.timer.stop()
        self.timer.start((self.delay*1000)+1)
        
    def flush(self):
        """If there is a signal queued up, send it now."""
        if self.args is None or self.block:
            return False
        self.emit(self.signal, *self.args)
        self.args = None
        return True
        
    def disconnect(self):
        self.block = True
    

def proxyConnect(source, signal, slot, delay=0.3):
    """Connect a signal to a slot with delay. Returns the SignalProxy
    object that was created. Be sure to store this object so it is not
    garbage-collected immediately."""
    sp = SignalProxy(source, signal, delay)
    sp.connect(sp, signal, slot)
    return sp
    
    
if __name__ == '__main__':
    from PyQt4 import QtGui
    app = QtGui.QApplication([])
    win = QtGui.QMainWindow()
    spin = QtGui.QSpinBox()
    win.setCentralWidget(spin)
    win.show()
    
    def fn(*args):
        print "Got signal:", args
    
    proxy = proxyConnect(spin, QtCore.SIGNAL('valueChanged(int)'), fn)
    
        
_______________________________________________
PySide mailing list
[email protected]
http://lists.pyside.org/listinfo/pyside

Reply via email to