68Fermer70
Kevin KoflerLe 12/05/2015 à 00:57
Folco (./68) :
Par contre, une question de parentalité : pourquoi les parents des QWidgets sont-ils des QWidgets, et non des QObjects ? C'est pas grave, mais c'est juste pour comprendre, j'ai lu la doc sur la hiérarchie des objets dans un programme, donc je comprends pas trop pourquoi dans une application, on passe de l'un à l'autre.

Parce que la notion d'appartenance pour les QWidgets est particulière: En plus de l'appartenance de QObject, elle signifie aussi que le widget est contenu graphiquement dans son parent. (En particulier, une fenêtre n'a pas de parent.) Un widget ne peut pas être contenu dans un objet non graphique.

Si tu veux absolument insérer une fenêtre dans une hiérarchie de QObject, quelque chose comme ça devrait fonctionner:
class WidgetWrapper : public QObject, public QScopedPointer<QWidget> {
  Q_OBJECT

  public:
    WidgetWrapper(QWidget *wrapped, QObject *parent = nullptr) : QObject(parent), QScopedPointer<QWidget>(wrapped) {}
    virtual ~WidgetWrapper() {}

  private:
    Q_DISABLE_COPY(WidgetWrapper)
}

et ensuite là où tu voudrais écrire new MyWidget(parent), tu écris new WidgetWrapper(new MyWidget(), parent) à la place.
- est-ce qu'il vaut mieux utiliser les macros SIGNAL/SLOT, ou la forme &classe::méthode des connections ? Ou est-ce qu'on s'en fout ? En fait, je ne sais pas pourquoi la méthode est surchargée, il y a des cas où on ne peut pas faire sans l'un ou l'autre ?

Les macros SIGNAL/SLOT étaient la seule forme jusqu'à Qt 4, et a été gardée surtout pour des raisons de compatibilité. La nouvelle forme est la version C++11 (enfin, elle est aussi permise en C++98 si le slot n'a pas plus de 6 arguments, le C++11 rajoute les templates variadiques, ce qui permet un nombre arbitraire d'arguments). L'avantage de la nouvelle forme est qu'elle permet de vérifier les types en temps de compilation au lieu de travailler avec des chaînes de caractéres (les macros SIGNAL et SLOT stringifient (!) leur contenu, toutes les vérifications de type sont faites lors de l'appel) et est donc aussi plus rapide. Le désavantage est qu'il faut préciser le nom de la classe. De plus, (avantage) tant qu'il y a une seule surcharge de la méthode, on n'a pas besoin de préciser les arguments, mais (désavantage) quand il y en a plusieurs, choisir la bonne méthode devient compliqué (et on ne peut pas utiliser les arguments optionnels avec une valeur par défaut).

Cf. http://wiki.qt.io/New_Signal_Slot_Syntax.
- la méthode se surcharge avec un "functor", c'est une simple fonction comme en C, ça ?

Un foncteur est un objet qui implémente operator(). Ça peut être un simple pointeur de fonction (mais en général, dans ce cas, il vaut mieux utiliser une méthode avec la syntaxe précédente), mais aussi une expression lambda C++11 (c'est surtout pour ça que cette syntaxe existe), un objet tr1::bind ou n'importe quel objet qui implémente un operator() avec les bons arguments.
- j'appelle le slot "trigger" quand on clique sur le bouton, est-ce que ça pourrait etre un problème d'appeler directement le signal "triggered" de l'action ? ou est-ce que c'est strictement identique ?

Connecter un signal directement à un autre est possible en théorie, mais tu es censé faire ça uniquement pour connecter un signal d'une autre classe directement à un signal de ta classe, pas l'inverse! Tu n'es pas censé appeler directement un signal d'une autre classe. Rien ne te dit que le slot trigger ne fasse pas plus qu'émettre le signal triggered. Donc la seule solution conforme á l'interface voulue est de connecter le signal reçu au slot trigger de l'action.
- est-ce qu'un destructeur d'objet qui a établi des connexions doit les détruire manuellement dans le destructeur, ou est-ce automatique ?

C'est automatique.