[prev in list] [next in list] [prev in thread] [next in thread]
List: pykde
Subject: [PyQt] How do you explicitly connect parameterless signals?
From: Russell Warren <russ () perspexis ! com>
Date: 2014-05-23 23:08:43
Message-ID: CAD91c14HyB-j6BgKbz8vRQWjq-MTP_2b7nBW94n1NWJdnc9=Yw () mail ! gmail ! com
[Download RAW message or body]
[Attachment #2 (multipart/alternative)]
I have some cases where I want to decorate my slots, where the decorator
has a typical (*args, **kwargs) catch-all signature. Unfortunately, when
doing this, I'm unable to connect the signals and slots properly to a
parameter-free overload when one with parameters is available.
From the docs I thought it could be explicitly done at the connection side
with the use of:
button.clicked[].connect(foo)
or it could be explicit at the slot instead (?) that we want the
parameter-free one via:
@pyqtSlot()
def foo():
but I can't get either of these to work. When my button slot has *args in
the params, I always get the 'checked' boolean.
How do I force PyQt5 to *not* connect up the version with the (bool, )
signature?
Full example code is below, with a stripped down example of the decorator
issue:
import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSlot
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
w.setWindowTitle('Signal connection checking')
b1 = QtWidgets.QPushButton("Connection to ()")
b2 = QtWidgets.QPushButton("Connection to (checked)")
b3 = QtWidgets.QPushButton("Connection to (*args)")
layout = QtWidgets.QVBoxLayout(w)
layout.addWidget(b1)
layout.addWidget(b2)
layout.addWidget(b3)
def bogus_decorator(f):
def wrapper(*args):
print "wrapper called with args = %r" % (args, )
return f() #<-- have to do this to make the code work
#should be the code below, but it fails since we call with
#an unexpected arg and get a corresponding TypeError.
#return f(*args) #<--- will fails since it passes an unexpected arg
return wrapper
def onVoidClick():
print "normal (void) clicked!"
def onBoolClick(checked):
print "normal (bool) clicked!"
@pyqtSlot() #<-- shouldn't this force the parameter-free overload?
@bogus_decorator
#@pyqtSlot() #<--- order does not matter
def onWrappedStarClick():
#this always gets called with the (bool) overload
print "Actual handler fired!"
b1.clicked.connect(onVoidClick)
b2.clicked.connect(onBoolClick)
#How to connect this next one so that it works like onVoidClick()?
# - explicitly defining the slot with @pyqtSlot() does not work
# - explicitly connecting an overload with clicked[()].connect doesn't work
b3.clicked.connect(onWrappedStarClick)
#b3.clicked[()].connect(onStarClick)
w.show()
sys.exit(app.exec_())
[Attachment #5 (text/html)]
<div dir="ltr"><div>I have some cases where I want to decorate my slots, where the \
decorator has a typical (*args, **kwargs) catch-all signature. Unfortunately, when \
doing this, I'm unable to connect the signals and slots properly to a \
parameter-free overload when one with parameters is available.<br>
</div><div><br></div><div><div>From the docs I thought it could be explicitly done at \
the connection side with the use of:<br></div></div><div><br></div><div><font \
face="courier new, monospace"> button.clicked[].connect(foo)</font></div>
<div><br></div><div>or it could be explicit at the slot instead (?) that we want the \
parameter-free one via:</div><div><br></div><div><font face="courier new, monospace"> \
@pyqtSlot()</font></div><div><font face="courier new, monospace"> def \
foo():</font></div>
<div><br></div><div>but I can't get either of these to work. When my button \
slot has *args in the params, I always get the 'checked' \
boolean.</div><div><br></div><div>How do I force PyQt5 to *not* connect up the \
version with the (bool, ) signature?</div>
<div><br></div><div>Full example code is below, with a stripped down example of the \
decorator issue:<br></div><div><br></div><div><div><font face="courier new, \
monospace">import sys</font></div><div><font face="courier new, monospace">from PyQt5 \
import QtWidgets</font></div>
<div><font face="courier new, monospace">from PyQt5.QtCore import \
pyqtSlot</font></div> <div><font face="courier new, \
monospace"><br></font></div><div><font face="courier new, monospace">app = \
QtWidgets.QApplication(sys.argv)</font></div><div><font face="courier new, \
monospace"><br></font></div><div><font face="courier new, monospace">w = \
QtWidgets.QWidget()</font></div>
<div><font face="courier new, monospace">w.setWindowTitle('Signal connection \
checking')</font></div><div><font face="courier new, \
monospace"><br></font></div><div><font face="courier new, monospace">b1 = \
QtWidgets.QPushButton("Connection to ()")</font></div>
<div><font face="courier new, monospace">b2 = QtWidgets.QPushButton("Connection \
to (checked)")</font></div><div><font face="courier new, monospace">b3 = \
QtWidgets.QPushButton("Connection to (*args)")</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier \
new, monospace">layout = QtWidgets.QVBoxLayout(w)</font></div><div><font \
face="courier new, monospace">layout.addWidget(b1)</font></div> <div><font \
face="courier new, monospace">layout.addWidget(b2)</font></div><div><font \
face="courier new, monospace">layout.addWidget(b3)</font></div><div><font \
face="courier new, monospace"><br></font></div><div><font face="courier new, \
monospace">def bogus_decorator(f):</font></div>
<div><font face="courier new, monospace"> def \
wrapper(*args):</font></div><div><font face="courier new, monospace"> \
print "wrapper called with args = %r" % (args, )</font></div> <div><font \
face="courier new, monospace"> return f() #<-- have to do this to make \
the code work</font></div><div><font face="courier new, monospace"> \
#should be the code below, but it fails since we call with</font></div>
<div><font face="courier new, monospace"> #an unexpected arg and get a \
corresponding TypeError.</font></div> <div><font face="courier new, monospace"> \
#return f(*args) #<--- will fails since it passes an unexpected \
arg</font></div><div><font face="courier new, monospace"> return \
wrapper</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">def \
onVoidClick():</font></div><div><font face="courier new, monospace"> print \
"normal (void) clicked!"</font></div><div> <font face="courier new, \
monospace"><br></font></div><div><font face="courier new, monospace">def \
onBoolClick(checked):</font></div><div><font face="courier new, monospace"> \
print "normal (bool) clicked!"</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier \
new, monospace">@pyqtSlot() #<-- shouldn't this force the parameter-free \
overload?</font></div><div><font face="courier new, \
monospace">@bogus_decorator</font></div>
<div><font face="courier new, monospace">#@pyqtSlot() #<--- order does not \
matter</font></div><div><font face="courier new, monospace">def \
onWrappedStarClick():</font></div><div><font face="courier new, monospace"> \
#this always gets called with the (bool) overload</font></div>
<div><font face="courier new, monospace"> print "Actual handler \
fired!"</font></div><div><font face="courier new, monospace"><br></font></div> \
<div><font face="courier new, \
monospace">b1.clicked.connect(onVoidClick)</font></div><div><font face="courier new, \
monospace">b2.clicked.connect(onBoolClick)</font></div><div><font face="courier new, \
monospace"><br></font></div>
<div><font face="courier new, monospace">#How to connect this next one so that it \
works like onVoidClick()?</font></div><div><font face="courier new, monospace"># - \
explicitly defining the slot with @pyqtSlot() does not work</font></div>
<div><font face="courier new, monospace"># - explicitly connecting an overload with \
clicked[()].connect doesn't work</font></div><div><font face="courier new, \
monospace">b3.clicked.connect(onWrappedStarClick)</font></div>
<div><font face="courier new, \
monospace">#b3.clicked[()].connect(onStarClick)</font></div><div><font face="courier \
new, monospace"><br></font></div><div><font face="courier new, \
monospace">w.show()</font></div><div> <font face="courier new, \
monospace"><br></font></div><div><font face="courier new, \
monospace">sys.exit(app.exec_())</font></div><div><br></div></div> </div>
[Attachment #6 (text/plain)]
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic