Salut !
J'ai pas refais de C++ serieusement depuis le siècle dernier, je m'y remet trèès doucement, à l'aide de Qt. Je pratique assez assiduement PySide6, donc je connais bien déjà certains concepts de la bête. Cependant me voilà bloqué dans la version C++ sur un truc sûrement trivial pour les connaisseurs, mais je ne sais pas trop quoi chercher, donc je me tourne vers vous.
La question, en gros, c'est comment connecter un signal d'un widget personnalisé à une méthode de la classe qui instancie le dit widget.
Je tente une petit bout de code minimaliste plutôt que me perdre dans des explications. Je vais essayer de le faire le plus précis et juste possible, résultats non-garantis.
D'abord la classe du widget personnalisé :
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
class CoolWidget : public QWidget {
Q_OBJECT
public:
explicit CoolWidget(QWidget *parent = nullptr) {
QHBoxLayout *cool_layout = new QHBoxLayout(this);
QPushButton *bouton1 = new QPushButton("Bouton 1");
QPushButton *bouton2 = new QPushButton("Bouton 2");
cool_layout->addWidget(bouton1);
cool_layout->addWidget(bouton2);
connect(bouton1, &QPushButton::clicked, /* je sais pas quoi mettre ici */);
/* pour que ça appelle la méthode
bouton1clicked() dans MainWindow */
}
}
et la classe MainWindow comme ça :
#include <QMainWindow>
#include <QWidget>
#include <QVBoxLayout>
#include "cool_widget.cpp"
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *central_widget = QWidget;
QVBoxLayout *main_layout = QVBoxLayout;
/*
* Ici je place des widgets dans ma main_layout.
*/
// Puis enfin le widget CoolWidget.
CoolWidget *cool_widget = CoolWidget;
main_layout->addWidget(cool_widget);
central_widget->setLayout(main_layout);
setCentralWidget(central_widget);
}
// Méthode à appeler lors de l'appui de bouton1 dans CoolWidget
void bouton1clicked() {
// Je fais des trucs quand le bouton est cliqué
}
}
(bon dans cet exemple il n'y a pas de headers pour simplifier, dans la version "vraie vie" tout est bien séparé en .h et .cpp)
Voilà, si quelqu'un peut me donner un coup de pouce, d'avance bien le merci :)
# 2 possibilité à la grosse louche
Posté par AncalagonTotof . Évalué à 4 (+3/-0).
Dans tous les cas, il faudrait définir un signal qui sera émit par une instance de
CoolWidget
quandbouton1
sera cliqué.La version lourde : ajouter un slot à
CoolWidget
pour recevoir le signalclicked
du bouton, puis dans ce slot, émettre le nouveau signal deCoolWidget
.La version moins lourde : connecter le signal
clicked
du bouton au nouveau signal deCoolWidget
(si, c'est possible !). L'émission declicked
par le bouton provoquera l'émission du signal deCoolWidget
.La solution lourde pourrait s'imposer s'il n'est pas possible ou pas souhaitable de faire transiter le même paramètre que celui du signal
clicked
(totalement de tête sans vérifier :bool checked
. Si les paramètres ne sont pas identiques, la connexion échouera). Dans ce cas, le slot deCoolWidget
aura ce paramètre, en fera quelque chose, ou pas, et fera l'émission du nouveau signal, sans paramètre, ou avec un paramètre différent selon le job.Quoi qu'il en soit, il est très largement préférable de connecter
cool_widget
àthis
dans le constructeur deMainWindow
.CoolWidget
n'a pas à connaîtreMainWindow
ni le slot qui doit recevoir son signal.[^] # Re: 2 possibilité à la grosse louche
Posté par WrathOfThePixel . Évalué à 2 (+1/-0).
Pardon pour ma noobitude, il doit y avoir un truc qui m'échappe, mais je ne vois pas comment l'une de ces deux méthodes va me dispenser d'avoir une reference à MainWindow dans CoolWidget, ce qu'effectivement je ne veut pas faire, et de toutes façon je ne saurais pas trop comment…
J'en suis venu à me dire qu'il me faudrait une classe "passe-plat" qui collecte les signaux pour les renvoyer dans les bon slots, mais je pense qu'on pourrais qualifier ça de méthode super-lourde du coup ?
Ou alors, je m'y prend mal pour la création de mon CoolWidget. J'ai du mal à croire que je suis le premier à vouloir faire un Widget perso, et il est probable que la méthode que j'utilide avec PySide ne soit pas la bonne pour le C++…
Ich bin perdu…
[^] # Re: 2 possibilité à la grosse louche
Posté par AncalagonTotof . Évalué à 2 (+1/-0).
Bon, aller, je fais les devoirs des gamins …
À vue, sans tester dans QtCreator :
CoolWidget
émet le signalsPasseUnTruc()
quand on clique surbouton1
. Mais c'est pas ses oignons de savoir où ça va.MainWindow
connecte le signalsPasseUnTruc()
de sonCoolWidget
vers son slotsPasseUnTrucCool()
pour réagir.[^] # Re: 2 possibilité à la grosse louche
Posté par WrathOfThePixel . Évalué à 2 (+1/-0).
Merci ca y est, j'ai (enfin) compris le principe. En nettoyant quelques typos pour que ça compile, ça fonctionne.
Sauf dans mon projet complet. J'ai droit à un
‘sPasseUnTruc’ was not declared in this scope
.Mais bon, je vais bien trouver pourquoi… Probablement.
[^] # Re: 2 possibilité à la grosse louche
Posté par AncalagonTotof . Évalué à 1 (+0/-0).
1) effacer totalement le répertoire de build. Des fois, c'est "magique" …
2) pas forcément nécessaire, mais plus sûr et plus propre : séparer les classes dans leurs fichiers .h/.cpp respectifs
Mieux ?
[^] # Re: 2 possibilité à la grosse louche
Posté par WrathOfThePixel . Évalué à 2 (+1/-0). Dernière modification le 03 octobre 2024 à 12:06.
C'est déjà tout en .h et .cpp, vu que la macro Q_OBJECT ne peut être que dans une en-tête, sinon elle est pas prise en compte. Je m'en suis rendu compte en compilant l'exemple que tu m'a donné, ça m'a pris un moment de grattage de tête aussi. Mais j'avais déjà fait ça bien dès le début.
Non c'était juste une erreur de débutant, j'avais oublié de mettre
Classe::
devant la définition dans le .cpp, tout bêtement.Merci encore en tout cas. J'avance bien maintenant.
Envoyer un commentaire
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.