Forgive Steven for his off-topic reply. I assume he's trying to goad you into having a more specific subject line. He knows darn well what PyQt, even if he has no experience with it.
And of course, as always you will want to post a complete, working example that we can see and comment on, rather than extracts of the code. It's much harder to comment on that. On 08/05/2017 08:28 AM, veek wrote: > 1. What exactly is a signal. In hardware, an interrupt can be viewed as a > signal and the voltage on a pin will suddenly jump to +5V as an indicator > that an interrupt has occurred. With Qt signals - if a widget-c++ code has > to 'signal' an event - what does it do? Basically a signal emission is a call to the main loop that indicates that an event has occurred, and then the main loop sees if there are any registered callbacks that want to be notified of this event, and if so it calls them, letting them execute. This is how event-driven programming works. The concept of signals and slots is very similar to explicit registering of callbacks in function. It differs only in form. So it sounds from your post that the book you are following is older and uses some of the older forms for signals and slots in PyQt. In recent years, PyQt has made some things nicer, make making signals just be members of the class that you can access through python as if they were a member of the instance. so my code in response to your questions will reflect this newer style. I recommend you look at the various online tutorials for PyQt (I still am using PyQt4, but PyQt5 will be nearly the same). > As a consequence of not understanding the above.. > > 2. How do you connect a single signal to multiple slots? Do the > slots/methods get called one by one? or are they treated as independent > threads and run on different cores? You simply have more than one connect() call. for example: button1.clicked.connect(callback1) button1.clicked.connect(callback2) Both callbacks will run when button1 emits its "clicked" signal. Then the callbacks are executed in some kind of order when the signal is emitted, one at a time. GUIs are typically single-threaded. That's why it's important to not have long-running code in a callback. If you do need to do something in a call back that takes a while, you could spawn a thread and turn the work over to a thread, and then return control of the GUI thread back to the main loop. > > 3. pg 130 of Summerfield > > class ZeroSpinBox(QObject): ^^^^^^^^ I'm guessing that should be QSpinBox, not QObject, as this class is just adding behavior to the spinbox. If the book really has it as QObject, I would suspect it is a mistake. But without seeing the entire example program, I cannot say. > def __init__(self, parent=None): > super(...blah initialize QObject with parent > self.connect(self, SIGNAL("valuedChanged(int)"), self.checkzero) > > def checkzero(self): > if self.value() == 0: > self.emit(SIGNAL("atzero"), self.zeros) > > basically when SpinBox gets set to zero we emit 'atzero' and return a zeros > counter. > > What i don't get is the valueChanged(int) bit.. he clearly defines an (int) > being passed to checkzero so shouldn't the definition reflect the same? > Mistake? Normally it should match the signature, yes. Whether this is a mistake, I don't know. I believe PyQt could be ignoring the parameters the slot callback doesn't have defined. And since he's calling self.value() to read the actual value, he doesn't really need the int parameter, though if it were me I'd use the parameter and not call self.value() at all. > A. additionally I did not understand short circuit signals where you can > drop the (type1, type2) in the signature and just do > SIGNAL("atzero") > > Is this doable ONLY in emit() or also in connect()?? As far as I know, only in the emit(). I'm not familiar with this "short circuit" thing. In fact I've never heard of it and have done a few things in PyQt. For defining signals, PyQt has defined a new method for creating signals that's much cleaner than using the SIGNAL() call: class ZeroSpinBox(QSpinbox): atzero = PyQt4.pyqtSignal() #could list arguments here if desired someother = PyQt4.pyqtSignal('int','bool') ... def checkzero(self, value): if value == 0: self.atzero.emit() Note that parameters to pyqtSignal can be either Python types that PyQt can marshall (int, float,str, any QObject-derived class etc), or C++ types as a name in a string. > 4. pg 131 'any data can be passed as arguments to the emit method and they > can be passed as Python objects' > > self.emit(SIGNAL("atzero"), 10, 20, 30) or > self.emit(SIGNAL("atzero"), [10, 20, 30]) > does he mean i can pass a SINGLE OBJECT of any python type or does he mean > multiple independent containers? > (assuming the definition matches) You can pass any number of extra parameters when emitting a signal. I've not used this feature before, so I'm not sure how it works exactly. > > 5. He says 'a signal with one argument is a Qt signal or a non-short-circuit > Python signal' > > So if I have a Qt widget in C++ and it emits a valueChanged(int) signal.. > okay he's going to have to convert our asm/x86 int to python-integer and > then call the python-method that was mapped to 'valueChanged' with the > python-integer argument OR the signal is being generated from Python code > itself AND WILL be converted to C++ datatype - huh???? why?? Basically what it means is that all the types used in signals are native C++ types. That's because, well, Qt is a C++ library. So at some point python objects have to be marshalled into C++ data types, and the reverse is also true. > I'm guessing there's some dispatch code that maintains a mapping table?? SO > why can't it differentiate between inhouse python widget and Qt-c++ widget?? Yes. It can't because it's written in C++. Any time you want to go between the C++ backend and Python, you have to marshall between > 6. "If we use the SIGNAL() function with a signalSignature (a possibly empty > parenthesized list of comma-separated PyQt types)..."?? > > how can it be an empty () list..?? If there's a list it's no longer empty.. He just means the call itself. SIGNAL() defines a signal with no signature. SIGNAL('int') defines a signal with one parameter, which will be a C++ int type (or Python integer) > > 7. What exactly is a Python signal vs a Qt signal originating from a C++- > asm-widget?? PyQt is a wrapper around C++Qt so.. where are the python > widgets?? That's a complicated question. Basically every PyQt object in Python consists of two objects. One is the underlying C++ QObject-based object which is opaque to Python, and one is the Python wrapper around that object that exposes the Qt object's attributes and methods to Python. Each call into Qt requires converting Python objects into C++ data types, and information returned from Qt calls is converted (wrapped) into python objects. This process is not always pythonic and sometimes you get C++-ism and Qt-isms such as QString's or QList's leaking into Python code. A signal emitted from Python code calls in the same C++ mechanism that dispatches signals from C++Qt code. It all goes through Qt, which is C++. In other words, signals are not propagated at the Python level, but rather at the underlying C++ level. The main loop is C++ and it's in charge. when a callback is executed, if it's a PyQt callback, it will be bubbled up through the Python interpreter into your python code, from Qt in C++. > 8. > class TaxRate(QObject): > def __init__(self): > super(TaxRate, self).__init__() > self.__rate = 17.5 > > def rate(self): > return self.__rate > > def setRate(self, rate): > if rate != self.__rate: > self.__rate = rate > self.emit(SIGNAL("rateChanged"), self.__rate) > > def rateChanged(value): > print "TaxRate changed to %.2f%%" % value > > vat = TaxRate() > vat.connect(vat, SIGNAL("rateChanged"), rateChanged) > vat.setRate(17.5) # No change will occur (new rate is the same) > vat.setRate(8.5) # A change will occur (new rate is different) > > Isn't this a mistake? self.connect( should be: > vat.connect(vat, SIGNAL("rateChanged"), rate) No. rateChanged is correct. There is no "rate" in the scope where where the vat.connect() call is made. -- https://mail.python.org/mailman/listinfo/python-list