2009-12-26 3 views
1

En C# afin de connecter un signal à fente (délégué à la méthode) tout ce que je fais est:La syntaxe Qt "connect" est très longue. Est-ce des astuces pour le raccourcir?

first.signal += second.slot 

Mais dans Qt, il est:

connect(& first, SIGNAL(signal(int, int, QString)), & second, SLOT(slot(int, int, QSTring))); 

Et celui-ci est compté court, normalement ils sont engendrés 2-3 lignes. Bien sûr, je comprends parfaitement que Qt ne se moque que des fichiers .h et pour .cpp ils sont liés à la syntaxe standard, mais est-ce des astuces/façons de rendre les connexions de slot de signal un peu plus courtes? Je connais l'auto-connexion des signaux aux slots en leur donnant des noms spéciaux, mais cela ne fonctionne que pour les signaux dans le fichier .ui. Des indices?

Répondre

1

Une astuce consisterait à utiliser QtCreator en tant qu'éditeur, car il vous permet de sélectionner des signaux et des emplacements à partir d'une liste déroulante au cours de la frappe.

Une réflexion apparemment sans rapport est que Qt s'efforce d'avoir une API plutôt verbeuse, car elle est plus facile à lire (et à retenir lors de l'écriture). Ainsi, ils évitent les abréviations et écrivent ce qu'ils signifient: QAbstractItemModel, setWindowTitle, etc. Pas QAbstItModel, setWinTit, etc. Plus de dactylographie, moins de malentendus et d'erreurs de liens (symboles manquants)

+0

QtCreator peut uniquement connecter des signaux et des slots Gui, ou un autre? – grigoryvp

+0

Lorsque vous tapez "connect (src, SIGNAL (", vous obtenez une liste de signaux disponibles ... même pour SLOT (... – e8johan

3

Si vous trouvez cela long et répétitif, vous pouvez utiliser des macros pour alléger la syntaxe. Par exemple:

#define S_i_i(x) x(int, int, QString) 
#define CONNECT(sx,x,tx,sy,y,ty) connect(&x, SIGNAL(tx(sx)), &y, SLOT(ty(sy))) 

CONNECT(signal, first, S_i_i, slot, second, S_i_i) 

L'inconvénient est que votre code perdra en lisibilité pour les autres à moins que vous ne choisissiez vos macros avec soin.

+1

Je pense qu'il est discutable de dire que cette syntaxe est plus légère ... En utilisant cette approche, vous auriez besoin d'un #define pour chaque signature de signal. Le seul endroit où cela pourrait être utile serait si vous avez besoin de connecter plusieurs slots au même signal, et dans ce cas vous avez déjà écrit une connexion (...) et un simple copier/coller fera l'affaire. –

+2

@daniel: ce que l'OP voulait c'est du code _shorter_. Il n'y a pas beaucoup de signatures, et elles pourraient être définies une fois pour toutes dans un en-tête commun, comme pour les délégués communs en C#. Cela étant dit, je ne trouve pas la façon originale de coder les signaux et les emplacements ennuyeux en premier lieu et je préférerais m'en tenir à cela, mais c'est juste une question de préférence personnelle :) – RedGlyph

1

Personnellement, je ne pense pas que ce soit si mauvais. Il suffit de l'écrire une fois pour chaque signal/slot et la plupart du temps vous n'avez pas à le toucher par la suite.

La chose la plus proche que j'ai trouvée qui aide dans une certaine mesure utilise boost :: bind/function avec le mécanisme signaux/slots. Il ne fournit pas une réponse directe à votre question, mais il est lié et vous pourriez en faire usage. Vous pouvez lire à ce sujet here.

3

Si vous faites des connexions à partir d'un signal dans un objet différent à une fente dans this objet, vous pouvez faire un raccourci, et utiliser ceci:

connect(& first, SIGNAL(signal(int, int, QString)), SLOT(slot(int, int, QSTring))); 

au lieu de ceci:

connect(& first, SIGNAL(signal(int, int, QString)), & second, SLOT(slot(int, int, QSTring))); 

qui supprime un peu de la connexion. Il y a d'autres raccourcis disponibles, je crois. Cependant, votre point général est valide, et est principalement un effet secondaire de la façon dont Qt fait son mécanisme de signal/slot. Si vous voulez vraiment une syntaxe plus concise en C++, vous pouvez regarder soit les bibliothèques Boost :: Signals ou SigC++, qui fournissent également un mécanisme de signal/slot. Soyez conscient des conflits de syntaxe, cependant.

+0

Boost :: Les signaux ne s'intègrent pas bien dans Qt, malheureusement :( – grigoryvp

6

Je sais que sur les signaux de connexion automatique à fentes en leur donnant des noms spéciaux, mais cela ne fonctionne que pour les signaux dans le fichier .ui

Cette approche peut être utilisée en dehors des fichiers .ui, vous pouvez appelez QMetaObject::connectSlotsByName où vous voulez.

+2

Faites attention quand et comment vous l'appelez ... si vous le faites dans un constructeur de classe de base, puis encore dans un constructeur de classe dérivée (par exemple), vous pourriez vous retrouver avec des fentes Il ne distingue pas ceux qui sont déjà connectés lorsqu'il est exécuté (vous pouvez probablement deviner comment je le sais maintenant.) –

0

Après quelques années, j'ai trouvé une sorte de solution qui peut rendre les connexions plus courtes.Solution est basée sur la réponse de @WildSeal et utilise cette simple macro:

#define QCON(a, b, c, d) VERIFY(QObject::connect(a, SIGNAL(b), c, SLOT(d))) 

Ainsi, le code long en question:

VERIFY(QObject::connect(first, SIGNAL(signal(int,int,QString)), second, SLOT(slot(int,int,QSTring)))); 

Will est devenu nettement plus courte:

QCON(first, signal(int,int,QString), second, slot(int,int,QString)); 

Tous les commentaires et suggestions sont les bienvenus :). Le seul inconvénient que j'ai trouvé en ce moment est que j'ai besoin d'une macro séparée pour connecter SIGNAL à SIGNAL. Mais comme une telle opération est un peu rare, je viens de présenter QCONS() et il fait un tour.

0

Une autre solution pour QT5 et C++ compilateurs 11 activés:

#define Q_CONNECT(sender, signal, receiver, slot) \ 
    QWidget::connect(\ 
     sender, &boost::remove_reference<boost::mpl::identity<decltype(*sender)>::type>::type::signal, \ 
     receiver, &boost::remove_reference<boost::mpl::identity<decltype(*receiver)>::type>::type::slot); 

#define Q_CONNECT_LAMBDA(sender, signal, receiver) \ 
    QWidget::connect(\ 
    sender, &boost::remove_reference<boost::mpl::identity<decltype(*sender)>::type>::type::signal, \ 
    receiver); 

Notez que boost :: :: mpl identité est nécessaire uniquement pour les compilateurs qui ne gèrent pas encore les éléments suivants (comme VS2010) :

decltype(expr)::member 

exemple d'utilisation:

Q_CONNECT(
    this, mySignalMethodName, 
    &someHandler, handlerMethodName); 

Q_CONNECT_LAMBDA(
    this, mySignalMethodName, 
    [=]() { handlerCode(); }); 

Plus:

  • pas besoin de taper dans les listes d'arguments;
  • pas besoin de dupliquer explicitement les informations de type;
  • pas besoin d'utiliser aucune des macros SIGNAL, SLOT, Q_SIGNAL, Q_SLOT;
  • tous les contrôles de compatibilité sont à la compilation.

Moins:

  • ne fonctionnera pas avec les méthodes surchargées.
Questions connexes