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