Kann jemand in einfachen Worten das Muster "Signale und Schlitze" erklären?
Antworten
Zu viele Anzeigen?Signale und Slots sind eine Möglichkeit, einen Sender (das Signal) von null oder mehr Empfängern (den Slots) zu entkoppeln. Nehmen wir an, Sie haben ein System mit Ereignissen, die Sie jedem anderen Teil des Systems, der an diesen Ereignissen interessiert ist, zur Verfügung stellen wollen. Anstatt den Code, der die Ereignisse erzeugt, fest mit dem Code zu verdrahten, der von diesen Ereignissen wissen will, würden Sie ein Signal- und Slotmuster verwenden.
Wenn der Sender ein Ereignis signalisiert (in der Regel durch Aufruf der Funktion, die mit diesem Ereignis/Signal verbunden ist), werden automatisch alle Empfänger für dieses Ereignis aufgerufen. Auf diese Weise können Sie während der Laufzeit des Programms je nach Bedarf Empfänger anschließen und abschalten.
Da diese Frage mit C++ getaggt wurde, hier ein Link zum Boost-Signale Bibliothek, die eine viel ausführlichere Erklärung enthält.
Ich denke, man kann Signale und Slots am besten beschreiben, wenn man sie als ein mögliches Umsetzungsinstrument für die Beobachter-Muster oder Veröffentlichen/Abonnieren-Muster . Es gibt eine signal
zum Beispiel buttonPressed(IdType)
auf der Verlagsseite. Jedes Mal, wenn die Taste gedrückt wird, werden alle Slots, die mit diesem Signal verbunden sind, aufgerufen. Slots befinden sich auf der Teilnehmerseite. Ein Slot könnte zum Beispiel sein sendMail(IdType)
.
Zusammen mit dem Ereignis "Taste gedrückt" würde der Slot wissen, welche Taste gedrückt wurde, da die ID übergeben wurde. IdType
steht für die Art der Daten, die über die Verbindung zwischen dem Publisher und dem Subscriber gesendet werden. Eine mögliche Operation für den Subscriber wäre connect(signal, slot)
die verbinden könnten buttonPressed(IdType)
mit sendMail(IdType)
so dass, wenn die Taste gedrückt wird, dieser bestimmte Slot aufgerufen wird.
Das Gute daran ist, dass der Teilnehmer (die Steckplatzseite) sich nicht um die Details des Signals kümmern muss. Er muss nur eine Verbindung herstellen. Daher haben wir hier eine große Anzahl von lose Kopplung . Sie können die Implementierung der Schaltflächen ändern, aber die Schnittstelle für die Steckplätze wäre immer noch die gleiche.
Blick auf Qt Signale/Schlitze o Boost-Signale für weitere Informationen.
Stellen Sie sich vor, Sie haben eine grafische Benutzeroberfläche in Ihrer Anwendung. Meistens wäre der Kontrollfluss nicht sehr linear, d.h. anstelle einer klaren Abfolge von Aktionen hätten Sie einen Benutzer, der mit der GUI interagiert (wie Schaltflächen, Menüs usw.).
Dies ist im Wesentlichen ein ereignisgesteuertes Modell, das sehr gut mit dem Signal- und Slot-Muster implementiert werden kann. Signale sind Ereignisse, die von Objekten (z. B. GUI-Komponenten) erzeugt werden, und Slots sind die Empfänger dieser Ereignisse.
Hier ein Beispiel: Stellen Sie sich vor, Sie haben ein Ankreuzfeld, das in Ihrer Programmiersprache als Objekt dargestellt wird. Mit diesem Kästchen können mehrere Dinge geschehen: Es kann umgeschaltet werden, was wiederum bedeutet, dass es entweder gesetzt oder nicht gesetzt ist. Das sind die Signale, die es aussenden kann. Wir werden sie checkboxToggled, checkboxSet und checkboxUnset nennen. Wie Sie sehen, sendet das Kontrollkästchen in diesem Beispiel immer das Signal checkboxToggled aus, wenn es umgeschaltet wird, aber auch genau eines der beiden anderen Signale, je nachdem, wie sich der Zustand ändert.
Stellen Sie sich nun vor, Sie hätten noch einige andere Objekte, nämlich ein Etikett, das in diesem Beispiel immer als Objekt existiert, aber "erscheinen" und "verschwinden" kann, und einen System-Piepton (ebenfalls durch ein Objekt repräsentiert), der einfach piepen kann. Das sind die Slots, die diese Objekte haben. Wir werden sie "messageAppear", "messageDisappear" und "beep" nennen.
Angenommen, Sie möchten, dass der Systempiepton jedes Mal ertönt, wenn das Kontrollkästchen umgeschaltet wird, und dass das Etikett erscheint oder verschwindet, je nachdem, ob der Benutzer das Kontrollkästchen aktiviert oder deaktiviert hat.
Sie würden also die folgenden Signale mit den folgenden Steckplätzen verbinden (Signale links, Steckplätze rechts):
checkboxToggled -> beep
checkboxSet -> messageAppear
checkboxUnset -> messageDisappear
Das ist im Grunde alles.
Signale und Slots können auch Argumente haben. Wenn Sie zum Beispiel einen Schieberegler verwenden, der einen numerischen Wert festlegt, möchten Sie den geänderten Wert zusammen mit dem ausgegebenen Signal senden, sobald der Benutzer den Schieberegler bewegt: sliderChanged(int).
Um wirklich etwas Sinnvolles zu tun, müssten Sie natürlich eigene Klassen schreiben, die eigene Signale und Slots enthalten. Das ist recht einfach und mit diesen eigenen Signalen und Slots haben Sie eine schöne Möglichkeit, mit der GUI oder anderen Teilen Ihres Codes ereignisgesteuert zu interagieren.
Beachten Sie, dass Signale und Slots oft symmetrisch sind, d. h., dass einem Slot oft ein Signal entspricht. Zum Beispiel kann ein Kontrollkästchen ein Signal ausgeben, wenn es umgeschaltet wird, aber es kann auch einen Slot enthalten, der das Kontrollkästchen selbst umschaltet. Es wäre einfach zu implementieren, Kontrollkästchen zu trennen, die immer entgegengesetzt zueinander gesetzt werden.
Ich nehme an, Sie sprechen von den Signalen und Slots von QT.
Es ist ganz einfach.
Eine Instanz einer Klasse kann ein Signal auslösen und eine andere Instanz einer anderen Klasse kann dieses Signal in einem Slot abfangen. Es ist so ähnlich wie ein Funktionsaufruf, nur dass derjenige, der die Funktion aufruft, nicht wissen muss, wer den Aufruf empfangen will.
Dies lässt sich am besten anhand eines Beispiels erläutern.
Die Klasse QPushButton hat ein Signal QPushButton::clicked(). Dieses Signal wird immer dann ausgelöst, wenn der Button angeklickt wird. Der PushButton muss nicht wissen, wer daran interessiert ist, um zu wissen, dass ein Klick stattgefunden hat. Er feuert einfach das Signal ab und wer daran interessiert ist, kann sich damit verbinden.
Der QDialog, in dem die Schaltfläche platziert ist, möchte in der Tat wissen, wann die Schaltfläche angeklickt wurde. Er hat den Slot MyDialog::buttonClicked(). Auf MyDialog c'tor müssen Sie das click()-Signal der Schaltfläche mit dem buttonClicked()-Slot des Dialogs verbinden, damit der Slot aufgerufen wird, wenn das Signal ausgelöst wird.
Eine Reihe von fortgeschrittenen Dingen:
- Argumente, ein Signal kann Argumente haben und diese Argumente können optional auch an den Slot übergeben werden.
- Thread-übergreifende Aufrufe - Wenn Sie eine Signal-Slot-Verbindung herstellen, die Thread-übergreifend sein muss, dann puffert QT die Signale automatisch und stellt sie in die Warteschlange des richtigen Threads. Dies geschieht zum Beispiel automatisch, wenn ein GUI-Thread mit einem Arbeitsthread kommunizieren muss.
Weitere Informationen finden Sie in der Dokumentation von QT.
Das beste Beispiel und die beste Erklärung, die ich für Signale und Slots gefunden habe, ist dieser Code-Projekt-Artikel .
- See previous answers
- Weitere Antworten anzeigen