Qt-Ereignisse und Signal / Slots

97

Was ist in der Qt-Welt der Unterschied zwischen Ereignissen und Signalen / Slots?

Ersetzt einer den anderen? Sind Ereignisse eine Abstraktion von Signalen / Slots?

Raphael
quelle

Antworten:

30

Die Qt-Dokumentation erklärt es wahrscheinlich am besten:

In Qt sind Ereignisse Objekte, die von der abstrakten QEventKlasse abgeleitet sind und Dinge darstellen, die entweder innerhalb einer Anwendung oder als Ergebnis externer Aktivitäten geschehen sind, über die die Anwendung Bescheid wissen muss. Ereignisse können von jeder Instanz einer QObjectUnterklasse empfangen und verarbeitet werden , sind jedoch für Widgets besonders relevant. In diesem Dokument wird beschrieben, wie Ereignisse in einer typischen Anwendung übermittelt und behandelt werden.

Ereignisse und Signal / Slots sind also zwei parallele Mechanismen, die das Gleiche bewirken. Im Allgemeinen wird ein Ereignis von einer externen Entität (z. B. Tastatur oder Mausrad) generiert und über die Ereignisschleife in ausgeliefert QApplication. Im Allgemeinen generieren Sie keine Ereignisse, es sei denn, Sie richten den Code ein. Sie können sie durch QObject::installEventFilter()Ereignisse in untergeordneten Objekten filtern oder behandeln, indem Sie die entsprechenden Funktionen überschreiben.

Signale und Slots sind viel einfacher zu generieren und zu empfangen und Sie können zwei beliebige QObjectUnterklassen verbinden. Sie werden über die Metaklasse abgewickelt (weitere Informationen finden Sie in Ihrer Datei moc_classname.cpp), aber der größte Teil der von Ihnen erzeugten Kommunikation zwischen Klassen verwendet wahrscheinlich Signale und Slots. Signale können sofort übermittelt oder über eine Warteschlange zurückgestellt werden (wenn Sie Threads verwenden).

Ein Signal kann erzeugt werden.

Harald Scheirich
quelle
Die zurückgestellte Warteschlange ist dieselbe wie die Warteschlangenereignisschleife, oder gibt es zwei Warteschlangen? eine für verzögerte Signale und eine für ein Ereignis?
Guillaume07
29
@ Raphael Schande über dich, dass du diese Antwort akzeptiert hast. - Der zitierte Absatz enthält nicht einmal die Wörter "Signal" oder "Steckplatz"!
Robert Siemer
1
@neuronet: Der Absatz wird mit "[es] erklärt es am besten" zitiert, was es nicht tut. Überhaupt nicht. Nicht mal ein bisschen.
Robert Siemer
@Robert Wenn diese kleine Intro-Zeile in "Zuerst überlegen wir, wie die Dokumente Ereignisse erklären, bevor wir fortfahren, um zu prüfen, wie sie mit Signalen zusammenhängen" geändert würde, wären Sie mit der Antwort einverstanden? Wenn ja, können wir die Antwort einfach bearbeiten, um sie zu verbessern, da dies ein kleiner Punkt ist und ich stimme zu, dass sie besser formuliert werden könnte. [Bearbeiten, das ist eine echte Frage: Da ich nicht sicher bin, ob der Rest viel besser ist ... aber nur weil der zitierte Teil keine Signale erwähnt, scheint es eine oberflächliche Sorge zu sein, wenn der Rest tatsächlich gut ist, was ich bin nicht vorausgesetzt .]
Eric
4
@neuronet, wenn Sie das Zitat vollständig entfernen, wird es die Antwort in meinen Augen verbessern. - Wenn Sie die gesamte Antwort entfernen, wird die gesamte Qualitätssicherung verbessert.
Robert Siemer
152

In Qt sind Signale und Ereignisse beide Implementierungen des Observer-Musters . Sie werden in unterschiedlichen Situationen eingesetzt, weil sie unterschiedliche Stärken und Schwächen haben.

Zunächst definieren wir genau, was wir unter "Qt-Ereignis" verstehen: eine virtuelle Funktion in einer Qt-Klasse, die Sie voraussichtlich in einer Ihrer Basisklassen erneut implementieren, wenn Sie das Ereignis behandeln möchten. Es hängt mit dem Muster der Vorlagenmethode zusammen .

Beachten Sie, wie ich das Wort " Handle " verwendet habe. In der Tat ist hier ein grundlegender Unterschied zwischen der Absicht von Signalen und Ereignissen:

  • Sie " behandeln " Ereignisse
  • Sie werden über Signalemissionen " benachrichtigt "

Der Unterschied besteht darin, dass Sie, wenn Sie das Ereignis "behandeln", die Verantwortung übernehmen, mit einem Verhalten zu "antworten", das außerhalb der Klasse nützlich ist. Stellen Sie sich beispielsweise eine App vor, auf der sich eine Schaltfläche mit einer Nummer befindet. Die App muss den Benutzer die Taste fokussieren lassen und die Nummer durch Drücken der Tastaturtasten "Auf" und "Ab" ändern. Andernfalls sollte die Schaltfläche wie normal funktionieren QPushButton(sie kann angeklickt werden usw.). In Qt wird dazu eine eigene kleine wiederverwendbare "Komponente" (Unterklasse von QPushButton) erstellt, die neu implementiert wird QWidget::keyPressEvent. Pseudocode:

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)

Sehen? Dieser Code enthält eine neue Abstraktion: ein Widget, das sich wie eine Schaltfläche verhält, jedoch einige zusätzliche Funktionen bietet. Wir haben diese Funktionalität sehr bequem hinzugefügt:

  • Da wir eine virtuelle Version neu implementiert haben, wurde unsere Implementierung automatisch in unsere Klasse eingekapselt. Wenn die Designer von Qt keyPressEventein Signal gemacht hätten, müssten wir entscheiden, ob wir das Signal erben QPushButtonoder nur extern verbinden wollen. Aber das wäre dumm, da in Qt immer erwartet wird, dass Sie erben, wenn Sie ein Widget mit einem benutzerdefinierten Verhalten schreiben (aus gutem Grund - Wiederverwendbarkeit / Modularität). Indem sie keyPressEventeine Veranstaltung durchführen, vermitteln sie ihre Absicht, keyPressEventdie nur ein grundlegender Baustein der Funktionalität ist. Wenn es ein Signal wäre, würde es wie eine benutzerbezogene Sache aussehen, wenn es nicht beabsichtigt ist.
  • Da die Basisklassenimplementierung der Funktion verfügbar ist, implementieren wir das Verantwortungskettenmuster einfach , indem wir unsere Sonderfälle (Auf- und Ab-Tasten) behandeln und den Rest der Basisklasse überlassen. Sie können sehen, dass dies fast unmöglich wäre, wenn keyPressEventein Signal wäre.

Das Design von Qt ist gut durchdacht - sie haben uns in die Erfolgsgrube geraten lassen, indem sie es einfach gemacht haben, das Richtige und das Falsche zu tun (indem sie keyPressEvent zu einem Ereignis gemacht haben).

Betrachten Sie auf der anderen Seite die einfachste Verwendung von QPushButton- einfach instanziieren und benachrichtigt werden, wenn darauf geklickt wird :

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

Dies ist eindeutig für den Benutzer der Klasse gedacht :

  • Wenn wir QPushButtonjedes Mal eine Unterklasse erstellen müssten, wenn eine Schaltfläche uns über einen Klick benachrichtigen soll, wären ohne guten Grund viele Unterklassen erforderlich ! Ein Widget, das messageboxbeim Klicken immer eine "Hallo Welt" anzeigt, ist nur in einem einzigen Fall nützlich - es ist also absolut nicht wiederverwendbar. Auch hier haben wir keine andere Wahl, als das Richtige zu tun - indem wir uns extern mit ihm verbinden.
  • Möglicherweise möchten wir mehrere Steckplätze anschließen clicked()- oder mehrere Signale anschließen sayHello(). Mit Signalen gibt es keine Aufregung. Mit Unterklassen müssten Sie sich hinsetzen und über einige Klassendiagramme nachdenken, bis Sie sich für ein geeignetes Design entscheiden.

Beachten Sie, dass sich einer der QPushButtonausgegebenen Orte clicked()in der mousePressEvent()Implementierung befindet. Das heißt nicht clicked()und mousePressEvent()sind austauschbar - nur dass sie verwandt sind.

Signale und Ereignisse haben also unterschiedliche Zwecke (aber sie hängen damit zusammen, dass Sie beide eine Benachrichtigung über ein Ereignis "abonnieren" können).

Stefan Monov
quelle
Ich habe die Idee. Das Ereignis ist pro Klasse, alle Instanzen einer Klasse reagieren gleich, alle rufen das gleiche QClassName :: -Ereignis auf. Das Signal ist jedoch pro Objekt, jedes Objekt kann eine eindeutige Signalschlitzverbindung haben.
德里克 薯条 德里克
39

Die Antworten gefallen mir bisher nicht. - Lassen Sie mich auf diesen Teil der Frage konzentrieren:

Sind Ereignisse eine Abstraktion von Signalen / Slots?

Kurze Antwort: nein. Die lange Antwort wirft eine „bessere“ Frage auf: Wie hängen Signale und Ereignisse zusammen?

Eine inaktive Hauptschleife (z. B. Qt) steckt normalerweise in einem select () -Aufruf des Betriebssystems fest. Dieser Aufruf lässt die Anwendung "schlafen", während sie eine Reihe von Sockets oder Dateien oder was auch immer an den Kernel weiterleitet und fragt: Wenn sich daran etwas ändert, lassen Sie den Aufruf select () zurückkehren. - Und der Kernel als Meister der Welt weiß, wann das passiert.

Das Ergebnis dieses select () -Aufrufs könnte sein: Neue Daten auf dem Socket verbinden sich mit X11, ein Paket zu einem UDP-Port, den wir abhören, ist eingegangen usw. - Dieses Zeug ist weder ein Qt-Signal noch ein Qt-Ereignis, und das Die Qt-Hauptschleife entscheidet selbst, ob sie die frischen Daten in die eine, die andere umwandelt oder ignoriert.

Qt kann eine Methode (oder mehrere) wie keyPressEvent () aufrufen und so effektiv in ein Qt-Ereignis verwandeln. Oder Qt sendet ein Signal aus, das praktisch alle für dieses Signal registrierten Funktionen nachschlägt und nacheinander aufruft.

Ein Unterschied dieser beiden Konzepte ist hier sichtbar: Ein Slot hat keine Stimme darüber, ob andere Slots, die für dieses Signal registriert sind, angerufen werden oder nicht. - Ereignisse ähneln eher einer Kette, und der Ereignishandler entscheidet, ob er diese Kette unterbricht oder nicht. Signale sehen in dieser Hinsicht wie ein Stern oder ein Baum aus.

Ein Ereignis kann ausgelöst werden oder vollständig in ein Signal umgewandelt werden (senden Sie einfach eines aus und rufen Sie nicht „super ()“ auf). Ein Signal kann in ein Ereignis umgewandelt werden (einen Ereignishandler aufrufen).

Was abstrahiert, was vom Fall abhängt: Das clicked () - Signal abstrahiert Mausereignisse (eine Taste bewegt sich nach unten und oben, ohne sich zu viel zu bewegen). Tastaturereignisse sind Abstraktionen von niedrigeren Ebenen (Dinge wie 果 oder é sind mehrere Tastenanschläge auf meinem System).

Vielleicht ist focusInEvent () ein Beispiel für das Gegenteil: Es könnte das clicked () -Signal verwenden (und damit abstrahieren), aber ich weiß nicht, ob es tatsächlich funktioniert.

Robert Siemer
quelle
4
Ich finde diesen Teil: "Ein Slot hat keine Abstimmung darüber, ob andere für dieses Signal registrierte Slots aufgerufen werden oder nicht" sehr aufschlussreich für den Unterschied zwischen Signalen und Ereignissen. Ich habe jedoch eine verwandte Frage: Was sind Nachrichten und wie hängen Nachrichten mit Signalen und Ereignissen zusammen? (wenn sie verwandt sind). Sind Nachrichten eine Abstraktion für Signale und Ereignisse? Können sie verwendet werden, um solche Interaktionen zwischen QObjects (oder anderen Objekten?)
user1284631 zu beschreiben
@axeoth: In Qt gibt es keine "Nachrichten". Nun, es gibt ein Meldungsfeld, aber das war es auch schon.
Stellen Sie Monica
@ KubaOber: Danke. Ich meinte "Ereignisse".
user1284631
3
@axeoth: Dann ist deine Frage Unsinn. Es lautet: "Was sind Ereignisse und wie hängen Ereignisse mit Signalen und Ereignissen zusammen?"
Stellen Sie Monica
@ KubaOber: Ich erinnere mich ein Jahr später nicht an den Kontext. Wie auch immer, es scheint, als hätte ich fast dasselbe gefragt wie beim OP: Was ist der Unterschied zwischen Ereignissen, Ereignissen und wie Ereignisse mit Signalen und Slots zusammenhängen? Was damals wirklich der Fall war, IIRC, suchte ich nach einer Möglichkeit, Qt-Signal- / Slot-gesteuerte Klassen in eine Art Nicht-Qt-Klassen zu verpacken, also suchte ich nach einer Möglichkeit, die erste aus der letzteren heraus zu befehlen. Ich stelle mir vor, dass ich überlegte, Ereignisse an sie zu senden, da dies bedeutete, dass ich nur Qt-Header einschließen musste und meine Klassen nicht zwingen musste, das Signal / die Slots zu implementieren.
user1284631
16

Ereignisse werden von der Ereignisschleife ausgelöst. Jedes GUI-Programm benötigt eine Ereignisschleife, unabhängig davon, ob Sie sie unter Windows oder Linux mit Qt, Win32 oder einer anderen GUI-Bibliothek schreiben. Außerdem hat jeder Thread eine eigene Ereignisschleife. In Qt ist "GUI Event Loop" (die Hauptschleife aller Qt-Anwendungen) ausgeblendet, aber Sie starten den Aufruf:

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

Nachrichten, die das Betriebssystem und andere Anwendungen an Ihr Programm senden, werden als Ereignisse gesendet.

Signale und Slots sind Qt-Mechanismen. Bei der Kompilierung mit moc (Metaobjekt-Compiler) werden diese in Rückruffunktionen geändert.

Ereignis sollte einen Empfänger haben, der es versenden sollte. Niemand sonst sollte dieses Ereignis bekommen.

Alle mit dem ausgesendeten Signal verbundenen Steckplätze werden ausgeführt.

Sie sollten Signale nicht als Ereignisse betrachten, denn wie Sie in der Qt-Dokumentation lesen können:

Wenn ein Signal ausgegeben wird, werden die daran angeschlossenen Slots normalerweise sofort ausgeführt, genau wie bei einem normalen Funktionsaufruf. In diesem Fall ist der Signal- und Slot-Mechanismus völlig unabhängig von einer GUI-Ereignisschleife.

Wenn Sie ein Ereignis senden, muss es einige Zeit warten, bis die Ereignisschleife alle zuvor aufgetretenen Ereignisse auslöst. Aus diesem Grund ist die Ausführung des Codes nach dem Senden eines Ereignisses oder Signals unterschiedlich. Der Code nach dem Senden eines Ereignisses wird sofort ausgeführt. Bei den Signal- und Slot-Mechanismen kommt es auf den Verbindungstyp an. Normalerweise wird es nach allen Slots ausgeführt. Mit Qt :: QueuedConnection wird es genau wie Ereignisse sofort ausgeführt. Überprüfen Sie alle Verbindungstypen in der Qt-Dokumentation .

Feuerlöscher
quelle
Dieser Satz gibt mir ein kurzes Verständnis der Unterschiede zwischen Qt-Signalschlitz und Ereignissen:When you send an event, it must wait for time when event loop dispatch all events that came earlier. Because of this, execution of the cod after sending event or signal is different
swdev
7

Es gibt einen Artikel, in dem die Ereignisverarbeitung ausführlich beschrieben wird: http://www.packtpub.com/article/events-and-signals

Hier wird der Unterschied zwischen Ereignissen und Signalen diskutiert:

Ereignisse und Signale sind zwei parallele Mechanismen, mit denen dasselbe erreicht wird. Im Allgemeinen sind Signale bei der Verwendung eines Widgets nützlich, während Ereignisse bei der Implementierung des Widgets nützlich sind. Wenn wir beispielsweise ein Widget wie QPushButton verwenden, sind wir mehr an seinem clicked () -Signal interessiert als an den Maus- oder Tastendruckereignissen auf niedriger Ebene, die zur Ausgabe des Signals geführt haben. Wenn wir jedoch die QPushButton-Klasse implementieren, sind wir mehr an der Implementierung von Code für Maus- und Schlüsselereignisse interessiert. Außerdem behandeln wir normalerweise Ereignisse, werden jedoch durch Signalemissionen benachrichtigt.

Dies scheint eine übliche Art zu sein, darüber zu sprechen, da die akzeptierte Antwort einige der gleichen Sätze verwendet.


Bitte beachten Sie die hilfreichen Kommentare zu dieser Antwort von Kuba Ober, die mich fragen lassen, ob sie möglicherweise etwas simpel sind.

Eric
quelle
Ich kann nicht sehen, wie zwei Mechanismen verwendet werden, um dasselbe zu erreichen - ich denke, es ist eine nutzlose Verallgemeinerung, die niemandem hilft.
Stellen Sie Monica am
@KubaOber nein, es hilft, die Details der unteren Ebene zu vermeiden. Würden Sie sagen, dass Python nicht hilfreich ist, weil Sie dasselbe in Maschinencode schreiben können? :)
Eric
2
Ich sage, dass der erste Satz des Zitats so weit verallgemeinert wird, dass er nutzlos ist. Technisch gesehen ist dies nicht falsch, sondern nur, weil Sie, wenn Sie dies wünschen, die Ereignisübergabe verwenden können, um die Funktionsweise des Signalschlitzmechanismus zu erreichen, und umgekehrt. Es wäre sehr umständlich. Nein, Signal-Slots sind nicht dasselbe wie Ereignisse, sie erreichen nicht dasselbe, und die Tatsache, dass beide existieren, ist entscheidend für den Erfolg von Qt. Das angeführte Tastenbeispiel ignoriert die allgemeine Funktionalität des Signalschlitzsystems vollständig.
Stellen Sie Monica am
1
"Ereignisse und Signale sind zwei parallele Mechanismen, mit denen im engen Rahmen einiger Widgets / Steuerelemente der Benutzeroberfläche dasselbe erreicht wird ." Der kühne Teil fehlt kritisch und macht das Zitat nicht hilfreich. Selbst dann kann man sich fragen, wie viel von dem "Gleichen" wirklich erreicht wird: Mit Signalen können Sie auf Klickereignisse reagieren, ohne einen Ereignisfilter im Widget zu installieren (oder vom Widget abzuleiten). Das Verzichten auf die Signale ist viel umständlicher und koppelt den Client-Code eng an die Steuerung. Das ist schlechtes Design.
Stellen Sie Monica am
1
Ereignisse sind ein allgegenwärtiges Konzept . Die spezielle Implementierung in Qt legt sie konkret als Datenstrukturen fest, an die übergeben wird event. Die Signale und Slots sind konkret Methoden, während der Verbindungsmechanismus eine Datenstruktur ist, mit der das Signal einen oder mehrere Slots aufrufen kann, die als damit verbunden aufgeführt sind. Ich hoffe, Sie sehen, dass es Unsinn ist, von Signal / Slots als einer "Teilmenge" oder "Variante" von Ereignissen zu sprechen, und umgekehrt. Sie sind wirklich verschiedene Dinge , die passieren zu ähnlichen Enden im Zusammenhang mit einigen Widgets verwendet werden. Das ist es. Je mehr Sie verallgemeinern, desto weniger hilfreich werden Sie IMHO.
Stellen Sie Monica am
5

TL; DR: Signale und Slots sind indirekte Methodenaufrufe. Ereignisse sind Datenstrukturen. Sie sind also ganz andere Tiere.

Das einzige Mal, wenn sie zusammenkommen, ist, wenn Slot-Aufrufe über Thread-Grenzen hinweg getätigt werden. Die Slot-Call-Argumente werden in eine Datenstruktur gepackt und als Ereignis an die Ereigniswarteschlange des empfangenden Threads gesendet. Im empfangenden Thread QObject::evententpackt die Methode die Argumente, führt den Aufruf aus und gibt möglicherweise das Ergebnis zurück, wenn es sich um eine blockierende Verbindung handelt.

Wenn wir bereit sind, das Vergessen zu verallgemeinern, könnte man sich Ereignisse als eine Möglichkeit vorstellen, die eventMethode des Zielobjekts aufzurufen . Dies ist nach einer Mode ein indirekter Methodenaufruf - aber ich denke nicht, dass es eine hilfreiche Art ist, darüber nachzudenken, selbst wenn es eine wahre Aussage ist.

Stellen Sie Monica wieder her
quelle
2

Ereignisse (im allgemeinen Sinne der Benutzer- / Netzwerkinteraktion) werden normalerweise in Qt mit Signalen / Slots behandelt, aber Signale / Slots können viele andere Dinge tun.

QEvent und seine Unterklassen sind im Grunde genommen nur kleine standardisierte Datenpakete, mit denen das Framework mit Ihrem Code kommunizieren kann. Wenn Sie auf irgendeine Weise auf die Maus achten möchten, müssen Sie sich nur die QMouseEvent-API ansehen, und die Bibliotheksdesigner müssen das Rad nicht jedes Mal neu erfinden, wenn Sie herausfinden müssen, was die Maus in einer Ecke von getan hat die Qt-API.

Es ist wahr, dass Ihr Slot mit ziemlicher Sicherheit eine QEvent-Unterklasse als Argument akzeptiert, wenn Sie auf Ereignisse warten (im allgemeinen Fall).

Vor diesem Hintergrund können Signale und Slots sicherlich ohne QEvents verwendet werden, obwohl Sie feststellen werden, dass der ursprüngliche Anstoß zur Aktivierung eines Signals häufig eine Art Benutzerinteraktion oder eine andere asynchrone Aktivität ist. Manchmal erreicht Ihr Code jedoch gerade einen Punkt, an dem das Abfeuern eines bestimmten Signals das Richtige ist. Zum Beispiel ein Signal an einen angeschlossenen abzufeuern Fortschrittsbalken während eines langen Prozesses beinhalten keine QEvent bis zu diesem Punkt.

jkerian
quelle
2
"Ereignisse werden normalerweise in Qt mit Signalen / Slots behandelt" - eigentlich nein ... QEvent-Objekte werden immer über überladene Virtuals weitergegeben! Zum Beispiel gibt es in QWidget kein Signal "keyDown" - stattdessen ist keyDown eine virtuelle Funktion.
Stefan Monov
Stimmen Sie mit
Stefan überein
1
@Stefan: Ich würde argumentieren, dass nur wenige Qt-Apps keyDown überschreiben (und stattdessen meistens Signale wie QAbstractButton :: clicked und QLineEdit :: editorFinished verwenden), um "typisch" zu rechtfertigen. Ich habe sicherlich schon einmal Tastatureingaben vorgenommen, aber es ist nicht die übliche Art, Ereignisse zu behandeln.
Jkerian
Nach Ihrer Bearbeitung (um zu verdeutlichen, was Sie unter "Ereignis" verstehen) ist Ihr Beitrag nun korrekt. Ich verzichte jedoch darauf, solche Wörter wiederzuverwenden. Die Dinge sind schlammig genug, ohne Signale als "eine Art von Ereignissen" zu bezeichnen.
Stefan Monov
2

Ich habe diese Frage beim Lesen von 'Event Processing' von Leow Wee Kheng gefunden. Es heißt auch:

Geben Sie hier die Bildbeschreibung ein

Jasmine Blanchette sagt:

Der Hauptgrund, warum Sie Ereignisse anstelle von Standardfunktionsaufrufen oder Signalen und Slots verwenden würden, besteht darin, dass Ereignisse sowohl synchron als auch asynchron verwendet werden können (abhängig davon, ob Sie sendEvent () oder postEvents () aufrufen, während Sie eine Funktion aufrufen oder aufrufen Ein Steckplatz ist immer synchron. Ein weiterer Vorteil von Ereignissen besteht darin, dass sie gefiltert werden können.

francek
quelle
1

Eine weitere kleine pragmatische Überlegung: Das Senden oder Empfangen von Signalen erfordert das Erben, QObjectwährend ein Objekt jeder Vererbung ein Ereignis posten oder senden kann (seit Sie es aufrufen QCoreApplication.sendEvent()oder postEvent()). Dies ist normalerweise kein Problem, aber: um Signale zu verwenden, muss PyQt seltsamerweise QObjectdie erste Superklasse sein. und Sie möchten möglicherweise Ihre Vererbungsreihenfolge nicht neu anordnen, nur um Signale senden zu können.)

bootchk
quelle
-1

Meiner Meinung nach sind Ereignisse völlig überflüssig und könnten verworfen werden. Es gibt keinen Grund, warum Signale nicht durch Ereignisse oder Ereignisse durch Signale ersetzt werden könnten, außer dass Qt bereits so eingerichtet ist, wie es ist. Signale in der Warteschlange werden von Ereignissen umschlossen, und Ereignisse können möglicherweise von Signalen umschlossen werden, zum Beispiel:

connect(this, &MyItem::mouseMove, [this](QMouseEvent*){});

Würde die mouseMoveEvent()in QWidget(aber nicht QQuickItemmehr in) enthaltene Komfortfunktion ersetzen und mouseMoveSignale verarbeiten, die ein Szenenmanager für das Objekt ausgeben würde. Die Tatsache, dass das Signal von einer externen Entität im Namen des Elements ausgesendet wird, ist unwichtig und kommt in der Welt der Qt-Komponenten häufig vor, obwohl dies angeblich nicht zulässig ist (Qt-Komponenten umgehen diese Regel häufig). Aber Qt ist ein Konglomerat aus vielen verschiedenen Designentscheidungen und aus Angst, alten Code zu brechen (was sowieso oft genug passiert), ziemlich in Stein gemeißelt.

user1095108
quelle
Ereignisse haben den Vorteil QObject, dass sie bei Bedarf die Eltern-Kind-Hierarchie weitergeben. Signal- / Steckplatzverbindungen sind nur ein Versprechen, eine Funktion direkt oder indirekt aufzurufen, wenn eine bestimmte Bedingung erfüllt ist. Es gibt keine zugeordnete Handhabungshierarchie mit Signalen und Slots.
anonym
Sie könnten ähnliche Ausbreitungsregeln mit Signalen implementieren. Es gibt keine Regel. dass ein bestimmtes Signal nicht erneut an ein anderes Objekt (Kind) ausgegeben werden kann. Sie können acceptedeinem Signal und den Slots, die es verarbeiten , einen Referenzparameter hinzufügen oder eine Struktur als Referenzparameter mit einem acceptedFeld haben. Aber Qt hat die Designentscheidungen getroffen und sie sind jetzt in Stein gemeißelt.
user1095108
1
Sie implementieren Ereignisse im Grunde nur neu, wenn Sie dies so tun, wie Sie es vorschlagen.
Fabio A.
@ FabioA. Darum geht es in der Frage des OP. Ereignisse und Signale können / könnten sich gegenseitig ersetzen.
user1095108
Wenn Sie Ereignisse neu implementieren, ersetzen Sie keine Ereignisse. Mehr dazu: Signale werden zusätzlich zu Ereignissen implementiert . Sie benötigen eine Art "Ereignissystem", um einigen anderen Ereignisschleifen, möglicherweise in einem Thread, der nicht Ihnen gehört, mitzuteilen, dass irgendwann in der Zukunft irgendwo eine bestimmte Funktion ausgeführt werden muss.
Fabio A.