Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Le système des signaux et des slots en PyQt et le type NoneType

+4 votes

Si je veux créer un Signal de ce type :

signal = pyqtSignal([QListWidgetItem], ['NoneType'])

Au lancement du code j'ai un beau message d'erreur :

TypeError: C++ type 'NoneType' is not supported as a pyqtSignal() type argument type

Mais si je ne mets pas l'argument NoneType et qu'un objet de ce type est passé au signal ça me donne :

TypeError: GrubList.newCurrentItem[QListWidgetItem].emit(): argument 1 has unexpected type 'NoneType'

Sauf que je veux passer un argument de ce type (ou équivalent) à mon signal, puisque c'est ce qui est retourné par mon widget.

Comment faire dans ce cas-là ?
Est-ce qu'on peut seulement ?

demandé 2-Jun-2015 par Laërte (346 points)

2 Réponses

+4 votes
 
Meilleure réponse

Il est possible que ce soit un bug lié à ta version de PyQT 1
Une possible solution est d'encapsuler ce que tu veux remonter en signal dans une classe et d'utiliser une instance de cette classe comme signal.
1 : http://stackoverflow.com/questions/21102591/pyside-pyqt-signal-that-can-transmit-any-value-including-none

répondu 3-Jun-2015 par furankun (1,416 points)
sélectionné 4-Jun-2015 par Laërte

J'utilise PyQt5.3.2
Je ne sais pas si un bug a été reporté concernant cette issue.

C'est fait, j'utilise une classe perso avec un seul attribut, ça passe.

0 votes

hum... en jetant un coup d'oeil ici, apparement tu n'as pas besoin de spécifier une seconde option en utilisant pyqtSignal.

You don't need to specify a second option - it will be accepting a
pointer for your class type, which can already be a None value:

C'est à dire que dans ton exemple tu pourrais faire :

signal = pyqtSignal(MaClasse)

ensuite tu pourrais les utiliser comme suit :

inst.signal.emit(MaClasse())
inst.signal.emit(None)
répondu 2-Jun-2015 par boblinux (3,094 points)

Sauf qu'en pratique ça marche pas.
À l'éxecution de inst.signal.emit(None)
J'ai cette erreur : TypeError: inst.signal[MaClasse].emit(): argument 1 has unexpected type 'NoneType'

j'suis a sec là!

Il se trouve qu'avec un autre signal ta solution fonctionne.

Mon problème doit donc être légèrement différent de ce que j'ai présenté.
Je vérifie et je te dis.

Je poste le code entier concernant le signal ici, peut-être que tu verras quelque chose qui m'a échappé :

class GrubList(QFrame):

    newCurrentItem = pyqtSignal(QListWidgetItem)

    def __init__(self, parent=None):
        QFrame.__init__(self, parent)
        self.grub_list = QListWidget()
        self.grub_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self.grub_list.currentItemChanged.connect(self.currentItemChanged)

    @pyqtSlot(QListWidgetItem, QListWidgetItem)
    def currentItemChanged(self, current, previous):
        self.newCurrentItem.emit(current)

C'est tout. Si aucun objet n'est sélectionné par self.grub_list l'émission de mon signal échoue, avec l'erreur précisée auparavent.

Selon moi le problème vient du fait que tu cherches à utiliser ton pyqtSignal avec deux types différents(QListWidgetItem et NoneType), alors que tu l'as initialisé pour un type donné (QListWidgetItem).
Est-ce qu'un bloc "try except" dans ton currentItemChanged (pour vérifier que tu n'est pas dans le cas du None) ne pourrait pas faire l'affaire?

Est-ce qu'un bloc "try except" dans ton currentItemChanged (pour vérifier que tu n'est pas dans le cas du None) ne pourrait pas faire l'affaire?

Non parce que c'est sur le slot, justement, que je fais une condition (pour désactiver des widgets quand rien n'est sélectionné).

...