[PyQt] pyqtsignal() and None value

J Barchan jnbarchan at gmail.com
Wed Sep 5 11:33:16 BST 2018


On 5 September 2018 at 09:11, J Barchan <jnbarchan at gmail.com> wrote:

>
>
> On 4 September 2018 at 18:08, Maurizio Berti <maurizio.berti at gmail.com>
> wrote:
>
>> You are defining a specific signature in the signal:
>>
>> QtCore.pyqtSignal(int, str)
>>
>> this means that, despite the types you set in the method
>> (which Qt doesn't know anything of also, as you didn't use the Slot
>> decorator), whenever you emit a None (which is a NoneType, not int, nor
>> str) Qt will try to "translate" it to the valid signature you assigned.
>>
>> I don't know exactly why the int is that a high number (always high and
>> always random), but this probably makes sense for some C++ type signature,
>> as it seems to me that the number is always 32bit long and, in my case,
>> always negative.
>>
>> Anyway, if you really need to send None, you can use the generic "object"
>> signature in the signal definition, or, in your case, just go with this,
>> assuming the progress will never use negative numbers.
>>
>> def updateProgress(self,
>> val: int=-1,
>> text: str=''):
>>     if val is >= 0:
>>         self.progressBar.pb.setValue(val)
>>     if text:
>>         self.progressBar.label.setText(text)
>>
>> and then emit the text signal using -1 for val.
>>
>> Maurizio
>>
>>
>> 2018-09-04 18:16 GMT+02:00 J Barchan <jnbarchan at gmail.com>:
>>
>>> PyQt5.7.  I am having trouble `emit()`ing a signal and receiving its
>>> arguments correctly.  I have read
>>> http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html carefully.
>>>
>>> *Declaration*:
>>>
>>>     # class variable for "notifyProgress" signal, for displaying a
>>> progressbar
>>>     notifyProgress = QtCore.pyqtSignal(int, str)
>>>
>>> *Initialisation*:
>>>
>>> self.notifyProgress.connect(self.updateProgress)
>>>
>>> *Slot*:
>>>
>>>     def updateProgress(self, val: int, text: str):
>>>         # slot for self.notifyProgress
>>>         # eprpayrequestfunctions.runEpr() calls this to indicate
>>> progress
>>>         # if it passes an integer it's the desired value for the
>>> progressbar
>>>         # if it passes a string it's the desired value for the label
>>>         if val is not None:
>>>             self.progressBar.pb.setValue(val)
>>>         if text is not None:
>>>             self.progressBar.label.setText(text)
>>>
>>> *Signals*:
>>>
>>> 1. notifyProgress.emit(None, "Some text")
>>>
>>> 2. notifyProgress.emit(i / 2, None)
>>>
>>> *Behaviour in slot*:
>>>
>>> The problem is the passing of None from emit():
>>>
>>> 1. val arrives in slot as 1261196128.
>>>
>>> 2. text arrives in slot as '' (empty string).
>>>
>>> *Questions*:
>>>
>>>    - Where is this behaviour for None as an emit() parameter documented?
>>>    - What is the correct/best way for handling this correctly/easily?
>>>
>>>
>>> --
>>> Kindest,
>>> Jonathan
>>>
>>> _______________________________________________
>>> PyQt mailing list    PyQt at riverbankcomputing.com
>>> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>>>
>>
>>
>>
>> --
>> È difficile avere una convinzione precisa quando si parla delle ragioni
>> del cuore. - "Sostiene Pereira", Antonio Tabucchi
>> http://www.jidesk.net
>>
>
> I'm OK with the
> val: int=-1, but not with the
> text: str=''.  An int of -1 is happily an invalid value for me, butt the
> trouble is a str of '' is perfectly legal, and will be used :(
>
> (which Qt doesn't know anything of also, as you didn't use the Slot
>> decorator),
>>
>
> I don't mind adding a slot decorator if that would help.  But presumably
> it would not here, as you're saying my None value does not match the type
> correctly anyway, right?
>
> I did consider making it so there is only one parameter, and the type (int
> or str) indicates which of the two paths to follow in the slot.  I
> followed
> http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html carefully where
> it describes"The following code demonstrates the connection of overloaded
> signals:" but I couldn't get it to work: it *always* called the
> first/default overload, regardless of the parameter type ... :(
>
> I'm now thinking: could I cut my losses and pass (and receive?) a single
> parameter as an explicit QVariant (which we don't usually use from PyQt),
> so that a single receiver slot can correctly see the original type ---
> would that work/be advisable?
>
>
> --
> Kindest,
> Jonathan
>

OK, I gave QVariant (single parameter) a try.  *All* I had to was:

1. Declare signal as:

QtCore.pyqtSignal(QVariant)

2. Write slot like:

def updateProgress(self, val):
    if type(val) is int or type(val) is float:
        self.progressBar.pb.setValue(val)
    elif type(val) is str:
        self.progressBar.label.setText(val)

3. And then it works correctly with both emitter types (without caller
bothering with QVariant), like:

notifyProgress.emit(50)
notifyProgress.emit("Finishing...")

Is there any reason I should *not* be doing this, because it seems perfect
to me?



-- 
Kindest,
Jonathan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20180905/7c821a85/attachment-0001.html>


More information about the PyQt mailing list