Re: PyQT - Signals and Slots?

2016-10-10 Thread Michael Torrie
On 10/10/2016 07:32 AM, Veek M wrote:
> Whaaa...t?? Could someone explain what exactly is his grand design 
> besides being awfully circuitous? So he has some other Form thingy.. and 
> in that he sets up another mapping from ZeroSpinBox.atzero --> 
> ZeroSpinBox.announce  where's announce and atzero defined?

In your example code, "atzero" is implicitly defined as a signal in the
connect() call.  Under the hood in Qt, signals are all dispatched by
strings when you emit() the signal.  PyQt does allow you to define
signals in a more pythonic way using class variables:

class Foo(QWidget):
atzero = SIGNAL( signature )

The signature can be a list of python types, or strings describing the
C++ types.  This is where the C++ nature of Qt leaks into PyQt.  In C++
since the moc compiler takes C++ code and C++ type names and generates a
meta-class that defines signals in terms of strings (moc does basic
compile-time type checking), in Python we also have to provide
signatures in strings also if we need something more than core python
types (int, bool, etc).  This signature helps PyQt (well Qt really)
marshal the types properly when the signal's callback is called.

But yes the example is convoluted and circuitous.  I think it's just to
demonstrate how signals and slots work, though.  That's what the
comments make clear.  This isn't how you'd implement a real widget with
customized behavior.

In general I don't think widgets normally want to catch their own
signals.  There are other mechanisms for that.  Usually you subclass the
widget and then override the appropriate *Event() method. For example,
to do something special on value changes I believe you'd subclass
QSpinBox and override the changeEvent() method. Inside that you would
get your value, do your logic, and potentially emit a custom signal. And
of course calling the parent changeEvent() to propagate the event
through to the parent class.


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: PyQT - Signals and Slots?

2016-10-10 Thread Veek M
Mark Summerfield wrote:

> 
> The ZeroSpinBox is a tiny example designed to show how the signal/slot
> mechanism works. It is just a QSpinBox with the addition of
> remembering how many times (all the) ZeroSpinBox(es) have had a 0
> value.
> 
> Nowadays the connections would be made with a new improved syntax:
> 
> self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero) # OLD
> self.valueChanged.connect(self.checkzero) # NEW
> # or
> self.valueChanged[int].connect(self.checkzero) # NEW
> 
> Similarly the emit:
> self.emit(SIGNAL("atzero"), self.zeros) # OLD
> self.atzero.emit(self.zeros) # NEW
> 
> What's happening inside ZeroSpinBox? Whenever its value is set to 0 it
> calls its own checkzero() method, and this in turn emits an atzero
> signal with the number of zeros so far. Why does it do this? Just to
> show the mechanism. It doesn't matter whether you connect a widget to
> itself (unusual but done here), or to another widget (the norm).
> 
> See the book's website https://www.qtrac.eu/pyqtbook.html
> for all the source code including some updated with the new syntax.
> (But the book is old, so even the Python 3.1 examples aren't as
> Pythonic as they would be written in Python 3.4+.)

ah - okay, so i was on the right track - thanks :) cool that you hang 
out here :) 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: PyQT - Signals and Slots?

2016-10-10 Thread Mark Summerfield

The ZeroSpinBox is a tiny example designed to show how the signal/slot
mechanism works. It is just a QSpinBox with the addition of remembering
how many times (all the) ZeroSpinBox(es) have had a 0 value.

Nowadays the connections would be made with a new improved syntax:

self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero) # OLD
self.valueChanged.connect(self.checkzero) # NEW
# or
self.valueChanged[int].connect(self.checkzero) # NEW

Similarly the emit:
self.emit(SIGNAL("atzero"), self.zeros) # OLD
self.atzero.emit(self.zeros) # NEW

What's happening inside ZeroSpinBox? Whenever its value is set to 0 it
calls its own checkzero() method, and this in turn emits an atzero signal
with the number of zeros so far. Why does it do this? Just to show the
mechanism. It doesn't matter whether you connect a widget to itself
(unusual but done here), or to another widget (the norm).

See the book's website https://www.qtrac.eu/pyqtbook.html
for all the source code including some updated with the new syntax.
(But the book is old, so even the Python 3.1 examples aren't as Pythonic as 
they would be written in Python 3.4+.)
-- 
https://mail.python.org/mailman/listinfo/python-list


PyQT - Signals and Slots?

2016-10-10 Thread Veek M
I'm reading Rapid GUI Programming - Mark Summerfield with Python and QT 
pg 131. Basically the mechanism is an event table which maps a 'signal' 
to a 'function/slot' -correct?

  self.connect(dial, SIGNAL("valueChanged(int)"), spinbox.setValue)

Here, dial.valueChanged -> spinbox.setValue

 s.connect(w, SIGNAL("signalSignature"), functionName)
 s.connect(w, SIGNAL("signalSignature"), instance.methodName)
 s.connect(w, SIGNAL("signalSignature"), instance, 
SLOT("slotSignature"))

Here, w.signalSignature -> functionName
-> instance.methodName
-> instance.slotSignature

If signalSignature is a C++ implemented thingy then we got to pass type 
info as part of the mapping so "signalSignature(int, float, const char 
*). PyQT signals are any type and any number of args..


If the Slot-function is implemented in C++ it's better to use the SLOT() 
mechanism:
 self.connect(dial, SIGNAL("valueChanged(int)"), spinbox, 
SLOT("setValue(int)"))
Here, we are mapping dial.valueChanged(int) --> spinbox.setValue(int)


The part i found tricky was this:

class ZeroSpinBox(QSpinBox):
zeros = 0
def __init__(self, parent=None):
super(ZeroSpinBox, self).__init__(parent)
self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero)

def checkzero(self):
if self.value() == 0:
self.zeros += 1
self.emit(SIGNAL("atzero"), self.zeros)

ZeroSpinBox.valueChanged -> ZeroSpinBox.checkzero? Why is he mapping 
back to himself? Shouldn't it be widget-to-widget?

Then he raises a signal 'atzero' with one arg - the lack of a atzero() 
implies it's a 'short-circuit' signal so self.zeroes is a python data 
type. And in the book he says:

###
Here is how we connect to the signal in the form’s __init__() method:
zerospinbox = ZeroSpinBox()
...
self.connect(zerospinbox, SIGNAL("atzero"), self.announce)
Again, we must not use parentheses because it is a short-circuit signal. 
And
for completeness, here is the slot it connects to in the form:
def announce(self, zeros):
print "ZeroSpinBox has been at zero %d times" % zeros
###

Whaaa...t?? Could someone explain what exactly is his grand design 
besides being awfully circuitous? So he has some other Form thingy.. and 
in that he sets up another mapping from ZeroSpinBox.atzero --> 
ZeroSpinBox.announce  where's announce and atzero defined?





-- 
https://mail.python.org/mailman/listinfo/python-list