FAQ Qt 5 et erreurs courantes

FAQ Qt 5 et erreurs courantesConsultez toutes les FAQ
Nombre d'auteurs : 1, nombre de questions : 16, dernière mise à jour : 6 février 2022

Rappel : ce message est émis dans l'onglet du bas intitulé « Sortie de l'application » dans Qt Creator. Il est obtenu pendant l'exécution de la ligne connect() correspondante utilisant les macros SIGNAL
/SLOT
lorsque les conditions qui suivent ne sont pas remplies.
Depuis Qt 5/C++11, l'utilisation de ces macros est dépréciée et il est vivement conseillé d'utiliser la nouvelle syntaxe utilisant des pointeurs sur fonctions (membres) :
Notez l'absence de parenthèses, il ne s'agit pas d'appels de fonctions, nous ne faisons que passer les adresses des fonctions (ici membres).
connect
(emetteur, &
ClasseEmetteur::
nomDuSignal,
receveur, &
ClasseReceveur::
nomDuSlot);
Cette syntaxe présente les avantages de vérifier cette erreur à la compilation plutôt que durant l'exécution, et d'autoriser la conversion implicite des paramètres du signal vers ceux du slot.
Je vous conseille la lecture des articles suivants : Les signaux et slots dans Qt 5.4, Les signaux et slots avec Qt 5, de nouvelles possibilités et Differences between String-Based and Functor-Based Connections.
Ce message peut être dû à plusieurs raisons.
-
Une classe qui utilise les signaux et slots doit :
- hériter de
QObject
, directement ou par le biais de l'une de ses classes dérivées (par ex.QWidget
) ; - utiliser la macro
Q_OBJECT
;
- hériter de
-
Un slot doit être déclaré dans la classe comme ceci à l'aide du mot-clé
slots
; un signal avec le mot-clésignals
:
(Non obligatoire si vous utilisez la nouvelle syntaxe apparue avec Qt 5 présentée au début de sujet.)Sélectionnezpublic
slots
:// public, protected ou private
void
nomDuSlot(/* éventuels paramètres */
);signals
:
// = public depuis Qt 5, protected avant
void
nomDuSignal(/* éventuels paramètres */
); - Suite à une faute de frappe, il se peut que vous ayez mal orthographié le nom du signal/slot (casse incluse : clicked est différent de Clicked). Vérifiez donc la bonne concordance entre sa déclaration (dans la documentation de la classe ou votre .h) et son utilisation dans le
connect
(…); ; - Vous avez tout simplement oublié de le déclarer dans votre classe.
Commencez donc par vérifier ces éléments, et corrigez-les si besoin. (Notamment pour le rajout de la macro Q_OBJECT
, prenez soin d'exécuter qmake juste après. Il se peut que vous ayez à nettoyer (clean) et recompiler votre projet [menu « Compiler » dans Qt Creator] pour que la modification prenne effet.)
Si l'erreur persiste, deux autres cas peuvent se présenter.
1) Mauvaise concordance receveur/slot ou de l'émetteur/signal
Pour rappel la fonction connect(), dans son utilisation la plus classique, va connecter le signal d'une instance emetteur au slot d'une instance receveur :
Sélectionnez
|
à chaque émission du signal :emit emetteur-> nomDuSignal(/* valeurs transmises */ ),sera exécuté : receveur -> nomDuSlot(/* valeurs reçues depuis celles transmises */ ) |
il faut donc que le signal nomDuSignal() soit membre de la classe de emetteur, et que le slot soit nomDuSlot() de la classe de receveur.
Une erreur classique de débutant consiste à faire :
connect
(button, SIGNAL
(clicked()),
lineEdit, SLOT
(nomDuSlot()) );
nomDuSlot() étant un slot de votre classe, alors que lineEdit est une instance de la classe QLineEdit
: la classe QLineEdit
ne possédant évidemment pas votre slot, vous obtenez cette erreur No such slot QLineEdit
::
nomDuSlot(), car lineEdit->
nomDuSlot() n'existe pas, nous voulons this
->
nomDuSlot().
C'est le pointeur vers l'instance de votre classe (à savoir this
) qu'il vous faut fournir en 3e argument :
connect
(button, SIGNAL
(clicked()),
this
, SLOT
(nomDuSlot()) );
Il vous est possible dans ce cas d'omettre ce 3e argument, this
sera utilisé par défaut :
connect
(button, SIGNAL
(clicked()), SLOT
(nomDuSlot()) );
connect
(button, &
QPushButton
::
clicked, this
, &
VotreClasse::
nomDuSlot);
2) Tentative erronée de passer des arguments ou mention des noms des paramètres
Comme rappelé dans le 1) dans les commentaires du premier code, vous devez écrire entre parenthèses les types que prennent les signaux et slots.
Et seulement les types, pas les noms des paramètres ! Par ex. mentionner value dans SLOT(votreSlot(int
value)) est faux.
Attention également à ne pas confondre nouvelle et ancienne syntaxe. Dans l'ancienne syntaxe, NomClasse::
ne doit pas apparaître devant les noms du signal et du slot.
Vous ne pouvez pas ajouter vos propres arguments sur cette ligne, les seuls passés sont ceux transmis depuis le signal émis vers le slot. Le code suivant, qui a pour volonté de fixer le texte suite à l'appui sur le bouton, est par conséquent faux :
connect
(button, SIGNAL
(clicked()),
lineEdit, SLOT
(setText("Texte"
)) );
et vous donne le message No such slot QLineEdit
::
setText("Texte"
).
Veuillez consulter le sujet Comment passer des paramètres à mon slot lors du connect() ? pour savoir comment procéder.
À voir également
Rappel : ce message est émis dans l'onglet du bas intitulé « Sortie de l'application » dans Qt Creator. Il est obtenu pendant l'exécution de la ligne connect() correspondante utilisant les macros SIGNAL
/SLOT
lorsque les conditions qui suivent ne sont pas remplies.
Depuis Qt 5/C++11, l'utilisation de ces macros est dépréciée et il est vivement conseillé d'utiliser la nouvelle syntaxe utilisant des pointeurs sur fonctions (membres) :
Notez l'absence de parenthèses, il ne s'agit pas d'appels de fonctions, nous ne faisons que passer les adresses des fonctions (ici membres).
connect
(emetteur, &
ClasseEmetteur::
nomDuSignal,
receveur, &
ClasseReceveur::
nomDuSlot);
Cette syntaxe présente les avantages de vérifier cette erreur à la compilation plutôt que durant l'exécution, et d'autoriser la conversion implicite des paramètres du signal vers ceux du slot.
Je vous conseille la lecture des articles suivants : Les signaux et slots dans Qt 5.4, Les signaux et slots avec Qt 5, de nouvelles possibilités et Differences between String-Based and Functor-Based Connections.
Cette erreur signifie que dans la connexion que vous avez effectuée, les paramètres du slot ne sont pas compatibles avec ceux émis par le signal. Et vous pouvez le voir dans la partie qui suit ce message et mentionne les éléments impliqués.
Par exemple, un signal void
nomDuSignal(); ne pourra pas transmettre l'int
qu'attendrait un slot void
nomDuSlot(int
);.
Pour connecter un tel slot, vous devrez avoir un signal avec une forme proche de void
nomDuSignal(int
);, transmettant un int
.
Pour rappel la fonction connect(), dans son utilisation la plus classique, va connecter le signal d'une instance emetteur au slot d'une instance receveur :
Sélectionnez
|
à chaque émission du signal :emit emetteur-> nomDuSignal(/* valeurs transmises */ ),sera exécuté : receveur -> nomDuSlot(/* valeurs reçues depuis celles transmises */ ) |
De ce fait, pour garantir une bonne réception des valeurs depuis le slot, vous devez vous assurer que le signal sera bel et bien capable de les transmettre.
Si votre souhait n'est pas de transmettre ces valeurs depuis le signal, mais depuis des variables ou valeur littérales au niveau de la connexion, rendez-vous dans le sujet Comment passer des paramètres à mon slot lors du connect() ?.