104 votes

Événements Qt et Signal / Slots

Dans le monde Qt, quelle est la différence d'événements et de signaux / slots?

Est-ce que l'un remplace l'autre? Les événements sont-ils une abstraction du signal / des slots?

154voto

Stefan Monov Points 4257

Dans Qt, les signaux et les événements sont les deux implémentations du modèle Observateur. Ils sont utilisés dans des situations différentes, parce qu'ils ont des forces et des faiblesses.

Tout d'abord nous allons définir ce que nous entendons par "événement de Qt' exactement: une fonction virtuelle dans une classe Qt, vous êtes attendus à ré-écrire dans une classe de base de la vôtre si vous souhaitez gérer l'événement. C'est lié à la Méthode de Modèle de modèle.

Notez la façon dont j'ai utilisé le mot "gérer". Ici, en effet, une différence fondamentale entre l'intention de signaux et événements:

  • Vous "gérer" les événements
  • Vous "êtes notifié de" signal d'émissions

La différence est que lorsque vous "traiter" le cas, vous prenez la responsabilité de "répondre" à un comportement qui est utile à l'extérieur de la classe. Par exemple, considérons une application qui a un bouton avec un numéro dessus. L'application doit permettre à l'utilisateur de se concentrer sur le bouton et de modifier le numéro en appuyant sur les boutons "haut" et "bas" de votre clavier. Sinon, le bouton doit fonctionner comme une normale QPushButton (il peut être cliqué, etc). Dans Qt ceci est fait par la création de votre propre petit réutilisables "composant" (sous-classe de QPushButton), qui reimplements QWidget::événement keypressevent. Pseudo-code:

class NumericButton extends QPushButton
    private void addToNumber(int value):
        // ...

    reimplement base.keyPressEvent(QKeyEvent event):
        if(event.key == up)
            this.addToNumber(1)
        else if(event.key == down)
            this.addToNumber(-1)
        else
            base.keyPressEvent(event)

Voir? Ce code présente une nouvelle abstraction: un widget qui agit comme un bouton, mais avec quelques fonctionnalités supplémentaires. Nous avons ajouté cette fonctionnalité très facilement:

  • Depuis que nous avons ré-implémenté un virtuel, de notre la mise en œuvre devient automatiquement encapsulé dans notre classe. Si Qt, les designers avaient fait événement keypressevent un signal, nous aurions besoin de décider si hériter QPushButton ou juste à l'extérieur de connecter le signal. Mais ce serait stupide, puisque dans Qt vous êtes toujours devrait hériter lors de l'écriture d'un widget avec un comportement personnalisé (pour une bonne raison - de la possibilité de réutilisation/modularité). Donc, en faisant événement keypressevent un événement, ils expriment leur intention que l'événement keypressevent est juste un bloc de construction de base de la fonctionnalité. Si c'était un signal, il aurais l'air d'un utilisateur face chose, quand il n'est pas destiné à être.
  • Depuis la classe de base-mise en œuvre de la fonction est disponible, nous pouvons facilement mettre en œuvre la Chaîne de responsabilité motif par la gestion de nos cas particuliers (haut&bas) et en laissant le reste de la classe de base. Vous pouvez voir que ce serait presque impossible si l'événement keypressevent ont été un signal.

La conception de l'intervalle Qt est bien pensé - et ils nous ont fait tomber dans la fosse de succès par il est facile de faire la bonne chose et difficile de faire la mauvaise chose (en faisant événement keypressevent un événement).

D'autre part, envisager l'utilisation la plus simple de QPushButton - juste de l'instanciation, et averti lorsqu'il est cliqué:

button = new QPushButton(this)
connect(button, SIGNAL(clicked()), SLOT(sayHello())

C'est censé être fait par l' utilisateur de la classe:

  • si nous avions à la sous-classe QPushButton chaque fois que nous voulons que le bouton pour nous aviser d'un clic, qui nécessiterait beaucoup de sous-classes pour aucune bonne raison! Un widget qui affiche toujours un "Hello world" messagebox lorsque l'utilisateur clique dessus n'est utile que dans un seul cas - il est donc totalement non réutilisables. Encore une fois, nous n'avons pas le choix, mais de faire la bonne chose - en se connectant à l'extérieur.
  • nous pouvons souhaitez connecter plusieurs logements à clicked() - ou de connecter plusieurs signaux d' sayHello(). Avec des signaux il n'y a pas de chichi. Avec sous-classement, vous auriez à vous asseoir et de réfléchir à certains diagrammes de classes jusqu'à ce que vous décidez sur une conception appropriée.

Notez que l'un des endroits les QPushButton émet clicked() est dans ses mousePressEvent() mise en œuvre. Cela ne veut pas dire clicked() et mousePressEvent() sont interchangeables - seulement qu'ils sont liés.

Afin de signaux et événements ont des finalités différentes (mais sont liées en ce que les deux vous permettent de vous abonner à une notification de quelque chose qui se passe).

41voto

Robert Siemer Points 1323

Je n'aime pas les réponses. – Permettez-moi de me concentrer sur cette partie de la question:

Sont des événements d'une abstraction de signal/slots?

Réponse courte: non. La longue réponse soulève une "meilleure" question: Comment sont les signaux et les événements liés?

Un ralenti boucle principale (Qt par exemple) est généralement "coincé" dans un appel select() du système d'exploitation. Cet appel fait de l'application de "sommeil", alors qu'il passe un tas de douilles ou des fichiers ou que ce soit pour le noyau demander: si quelque chose change sur ces, laisser le select() de retour d'appel. – Et le noyau, comme le maître du monde, ne sait quand cela se produit.

Le résultat de cet appel select() pourrait être: de nouvelles données sur la socket se connecter à X11, un paquet à un port UDP nous écouter sur entrée, etc. – Ça n'est ni un signal Qt, ni un événement de Qt et Qt boucle principale décide elle-même si elle tourne les frais de données dans l'un, l'autre ou l'ignore.

Qt pourrait appeler une méthode (ou plusieurs) comme événement keypressevent(), a pour effet de transformer en un événement de Qt. Ou Qt émet un signal qui, en effet, cherche toutes les fonctions enregistrées pour ce signal, et les appelle l'un après l'autre.

Une différence de ces deux concepts est visible ici: un logement a pas de vote sur si d'autres emplacements enregistrés pour ce signal sera appelée ou non. – Les événements sont plus comme une chaîne, et le gestionnaire d'événement décide si elle interrompt la chaîne ou pas. Les signaux de ressembler à une star ou d'un arbre à cet égard.

Un événement peut déclencher ou être entièrement transformé en un signal (juste émettent un, et de ne pas l'appeler "super()"). Un signal peut être transformé en un événement (appel d'un gestionnaire d'événement).

Ce que les résumés de quoi dépend le cas: la clicked()-signal résumés des événements de la souris (bouton va vers le bas et de nouveau sans trop se déplaçant autour). Les événements de clavier sont des abstractions des niveaux inférieurs (des choses comme 果 ou é de plusieurs coups de clés sur mon système).

Peut-être que le focusInEvent() est un exemple du contraire: il pourrait utiliser (et donc abstrait), l'clicked() du signal, mais je ne sais pas si dans la réalité.

30voto

Harald Scheirich Points 7227

La Documentation de Qt explique probablement mieux

Dans Qt, les événements sont des objets, des dérivés de l'abstrait QEvent classe, qui représenter des choses qui se sont passées soit au sein d'une application ou d'un résultat de l'activité extérieure que l' l'application a besoin de les connaître. Les événements peuvent être reçues et traitées par toute instance d'une sous-classe QObject, mais ils sont particulièrement pertinents pour les widgets. Ce document décrit comment les événements sont livrés et traitées dans un application typique.

Donc, les événements et les signaux/slots sont deux mécanismes parallèles accomplir les mêmes choses, en général, un événement est généré par un organisme extérieur (par exemple, Clavier, Mouswheel) et sera livré par la boucle d'événements dans QApplication. En général, sauf si vous définissez le code que vous ne serez pas générer des événements. Vous pouvez les filtrer par QObject::installEventFilter() ou de gérer les événements en sous-classé objet en substituant les fonctions appropriées.

Les signaux et les Slots sont beaucoup plus faciles à générer et de recevoir et vous pouvez connecter deux QObject sous-classes. Ils sont gérés par le biais de la Métaclasse (jetez un oeil à votre moc_classname.cpp fichier pour plus de détails), mais la plupart des interclasses de communication que vous produirez sera probablement utiliser les signaux et les slots. Les signaux peuvent obtenir de l'offre immédiatement ou en différé, via une file d'attente (si vous êtes à l'aide de threads) Un signal peut être généré

19voto

firescreamer Points 280

Les événements sont envoyés par la boucle d'événements. Chaque programme GUI besoin de boucle d'événements, ce que vous écrivez Windows ou Linux, en utilisant Qt, WinApi ou de toute autre bibliothèque d'interface graphique. Ainsi chaque thread possède sa propre boucle d'événements. Dans Qt "GUI Boucle d'Événement" (la sorcière est la boucle principale de toutes les applications Qt) est caché, mais vous commencez à en appelant:

QApplication a(argc, argv);
return a.exec();

Les Messages d'OS et d'autres applications envoyer à votre programme sont expédiés dans les événements.

Les signaux et les slots sont Qt mécanisme, dans le processus de compilations à l'aide de moc (meta-object compilateur), il est modifié à des fonctions de rappel.

L'événement devrait avoir un récepteur, sorcière si l'expédition. Personne ne devrait obtenir de l'événement.

Tous les logements connecté signal émis sera exécuté.

Vous ne devriez pas penser à des Signaux d'événements, car comme vous pouvez le lire dans la doc Qt:

Lorsqu'un signal est émis, les logements qui y sont connectés sont généralement exécutées immédiatement, tout comme une fonction normale d'appel. Lorsque cela se produit, les signaux et les fentes mécanisme est totalement indépendant de l'interface graphique boucle d'événements.

Lorsque vous envoyez un événement, il doit attendre de temps lors de la boucle d'événement de l'expédition de tous les événements qui sont arrivés plus tôt. De ce fait, l'exécution de la morue après l'envoi de l'événement ou le signal est différent. La morue de la jachère d'envoi de l'événement sera exécuté immédiatement. Avec les signaux et les slots mécanisme dépendent du type de connexion. Normalement, il sera exécuté après toutes les machines à sous. À l'aide de Qt::QueuedConnection, il sera exécuté immédiatement, tout comme les événements. Vérifiez toutes les connexions de type à la Doc de Qt

2voto

jkerian Points 8328

Événements (dans un sens général de l'utilisateur/réseau d'interaction) sont généralement traités dans Qt avec les signaux/slots, mais les signaux/slots pouvez faire beaucoup d'autres choses.

QEvent et de ses sous-classes sont en fait que peu de données normalisées des packages pour le cadre de communiquer avec votre code. Si vous voulez faire attention à la souris, d'une certaine façon, vous n'avez qu'à regarder la QMouseEvent API, et la bibliothèque, les concepteurs n'ont pas à réinventer la roue à chaque fois que vous devez comprendre ce que la souris n'a dans un coin de l'intervalle Qt de l'API.

Il est vrai que si vous êtes en attente pour les événements (à nouveau dans le cas général), de la sorte, votre logement sera presque certainement accepter un QEvent sous-classe comme un argument.

Cela dit, les signaux et les slots peuvent certainement être utilisées sans QEvents, bien que vous trouverez que l'impulsion initiale pour l'activation d'un signal sera souvent une sorte d'interaction de l'utilisateur ou d'autres asynchrone de l'activité. Parfois, cependant, votre code sera juste arriver à un point où de tirer un certain signal sera la bonne chose à faire. Par exemple, de tirer un signal connecté à une barre de progression pendant un long processus n'implique pas une QEvent jusqu'à ce point.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X