Zdarzenia Qt i sygnał / sloty

98

W świecie Qt, jaka jest różnica wydarzeń i sygnałów / slotów?

Czy jedno zastępuje drugie? Czy zdarzenia są abstrakcją sygnału / szczelin?

Raphael
źródło

Odpowiedzi:

30

Dokumentacja Qt prawdopodobnie najlepiej to wyjaśnia:

W Qt zdarzenia są obiektami wywodzącymi się z QEventklasy abstrakcyjnej , które reprezentują rzeczy, które wydarzyły się w aplikacji lub w wyniku zewnętrznej aktywności, o której aplikacja musi wiedzieć. Zdarzenia mogą być odbierane i obsługiwane przez dowolną instancję QObjectpodklasy, ale są one szczególnie istotne w przypadku widżetów. Ten dokument opisuje, w jaki sposób zdarzenia są dostarczane i obsługiwane w typowej aplikacji.

Zatem zdarzenia i sygnały / szczeliny są dwoma równoległymi mechanizmami realizującymi te same rzeczy. Ogólnie rzecz biorąc, zdarzenie zostanie wygenerowane przez zewnętrzną jednostkę (na przykład klawiaturę lub kółko myszy) i zostanie dostarczone przez pętlę zdarzeń QApplication. Generalnie, jeśli nie skonfigurujesz kodu, nie będziesz generować zdarzeń. Możesz je filtrować QObject::installEventFilter()lub obsługiwać zdarzenia w obiekcie podklasowym, nadpisując odpowiednie funkcje.

Sygnały i sloty są znacznie łatwiejsze do generowania i odbierania, a ponadto można połączyć dowolne dwie QObjectpodklasy. Są one obsługiwane przez Metaclassę (zajrzyj do pliku moc_classname.cpp, aby uzyskać więcej informacji), ale większość komunikacji międzyklasowej, którą stworzysz, będzie prawdopodobnie używać sygnałów i gniazd. Sygnały mogą być dostarczane natychmiast lub odraczane przez kolejkę (jeśli używasz wątków).

Sygnał może zostać wygenerowany.

Harald Scheirich
źródło
kolejka odroczona jest taka sama jak pętla zdarzeń kolejki, czy istnieją dwie kolejki? jeden dla odroczonych sygnałów i dla zdarzenia?
Guillaume
30
@Raphael, wstydź się, że zaakceptowałeś tę odpowiedź. - Cytowany akapit nie zawiera nawet słów „sygnał” lub „szczelina”!
Robert Siemer
1
@neuronet: akapit jest cytowany ze słowem „[to] wyjaśnia to najlepiej”, co tak nie jest. Ani trochę. Ani trochę.
Robert Siemer
@Robert, więc jeśli ta mała linijka wprowadzająca została zmieniona na „Najpierw zastanówmy się, jak dokumenty wyjaśniają zdarzenia, zanim przejdziemy do rozważenia, jak są one powiązane z sygnałami”, czy odpowiedź byłaby w porządku? Jeśli tak, możemy po prostu edytować odpowiedź, aby ją poprawić, ponieważ jest to drobna kwestia i zgadzam się, że można by było lepiej sformułować ją. [Edycja to prawdziwe pytanie: ponieważ nie jestem pewien, czy reszta jest znacznie lepsza ... ale tylko dlatego, że cytowana część nie wspomina o sygnałach, wydaje się powierzchownym zmartwieniem, jeśli reszta jest rzeczywiście dobra, a jestem nie zakładam .]
eric
4
@neuronet, jeśli całkowicie usuniesz cytat, poprawi to odpowiedź w moich oczach. - Jeśli usuniesz całą odpowiedź, poprawi to całą kontrolę jakości.
Robert Siemer
152

W Qt sygnały i zdarzenia są implementacjami wzorca Observer . Są używane w różnych sytuacjach, ponieważ mają różne mocne i słabe strony.

Przede wszystkim zdefiniujmy dokładnie, co rozumiemy przez „zdarzenie Qt”: funkcję wirtualną w klasie Qt, którą należy ponownie zaimplementować w swojej klasie bazowej, jeśli chcesz obsłużyć zdarzenie. Jest to związane ze wzorcem metody szablonu .

Zwróć uwagę, jak użyłem słowa „ uchwyt ”. Rzeczywiście, oto podstawowa różnica między intencją sygnałów a wydarzeniami:

  • Ty „ handle ” wydarzenia
  • Ty „ otrzymywać powiadomienia o ” emisji sygnału

Różnica polega na tym, że kiedy „obsługujesz” wydarzenie, bierzesz na siebie odpowiedzialność za „zareagowanie” zachowaniem, które jest przydatne poza klasą. Na przykład weźmy pod uwagę aplikację, która ma przycisk z numerem. Aplikacja musi pozwolić użytkownikowi skupić się na przycisku i zmienić numer, naciskając klawisze „w górę” i „w dół”. W przeciwnym razie przycisk powinien działać normalnie QPushButton(można go kliknąć itp.). W Qt odbywa się to poprzez utworzenie własnego małego „komponentu” wielokrotnego użytku (podklasy QPushButton), który jest ponownie implementowany QWidget::keyPressEvent. Pseudo kod:

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)

Widzieć? Ten kod przedstawia nową abstrakcję: widget, który działa jak przycisk, ale ma dodatkowe funkcje. Bardzo wygodnie dodaliśmy tę funkcjonalność:

  • Odkąd ponownie zaimplementowaliśmy wirtualny, nasza implementacja automatycznie została umieszczona w naszej klasie. Gdyby projektanci Qt stworzyli keyPressEventsygnał, musielibyśmy zdecydować, czy odziedziczyć, QPushButtonczy po prostu połączyć się zewnętrznie z sygnałem. Ale to byłoby głupie, ponieważ w Qt zawsze oczekuje się, że będziesz dziedziczyć, pisząc widżet z niestandardowym zachowaniem (nie bez powodu - wielokrotnego użytku / modułowości). Tworząc keyPressEventwydarzenie, przekazują swój zamiar, który keyPressEventjest tylko podstawowym budulcem funkcjonalności. Gdyby to był sygnał, wyglądałby jak obiekt skierowany do użytkownika, kiedy nie jest przeznaczony.
  • Ponieważ implementacja funkcji w klasie bazowej jest dostępna, łatwo implementujemy wzorzec łańcucha odpowiedzialności , obsługując nasze specjalne przypadki (klawisze w górę iw dół), a resztę pozostawiając klasie bazowej. Jak widać, byłoby to prawie niemożliwe, gdyby keyPressEventbył to sygnał.

Projekt Qt jest dobrze przemyślany - sprawili, że wpadliśmy w otchłań sukcesu , ułatwiając zrobienie właściwej rzeczy i trudną do zrobienia złej (poprzez uczynienie keyPressEvent wydarzeniem).

Z drugiej strony rozważ najprostsze użycie QPushButton- wystarczy utworzyć jego instancję i otrzymać powiadomienie, gdy zostanie kliknięty :

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

Jest to wyraźnie przeznaczone do wykonania przez użytkownika klasy:

  • gdybyśmy musieli podklasować za QPushButtonkażdym razem, gdy chcemy, aby jakiś przycisk powiadamiał nas o kliknięciu, wymagałoby to wielu podklas bez dobrego powodu! Widżet, który messageboxpo kliknięciu zawsze pokazuje „Witaj, świecie” , jest przydatny tylko w jednym przypadku - więc nie można go używać ponownie. Ponownie, nie mamy innego wyboru, jak tylko postąpić właściwie - łącząc się z nim zewnętrznie.
  • możemy chcieć podłączyć kilka gniazd do clicked()- lub podłączyć kilka sygnałów do sayHello(). Z sygnałami nie ma zamieszania. W przypadku tworzenia podklas musiałbyś usiąść i przemyśleć kilka diagramów klas, dopóki nie zdecydujesz się na odpowiedni projekt.

Należy pamiętać, że jednym z miejsc, QPushButtonemituje clicked()w jego mousePressEvent()realizacji. To nie znaczy clicked()i mousePressEvent()są wymienne - tylko, że są powiązane.

Tak więc sygnały i zdarzenia mają różne cele (ale są ze sobą powiązane, ponieważ oba pozwalają „zasubskrybować” powiadomienie o czymś, co się dzieje).

Stefan Monov
źródło
Mam pomysł. Event jest na klasę, wszystkie instancje klasy będą reagować tak samo, wszystkie będą wywoływać to samo QClassName :: event. Ale sygnał jest na obiekt, każdy obiekt może mieć swoje unikalne połączenie gniazda sygnału.
炸鱼 薯条 德里克
39

Jak dotąd nie podobają mi się odpowiedzi. - Skoncentruję się na tej części pytania:

Czy zdarzenia są abstrakcją sygnału / szczelin?

Krótka odpowiedź: nie. Długa odpowiedź nasuwa „lepsze” pytanie: w jaki sposób sygnały i zdarzenia są powiązane?

Bezczynna główna pętla (na przykład Qt) jest zwykle „blokowana” w wywołaniu select () systemu operacyjnego. To wywołanie sprawia, że ​​aplikacja „usypia”, podczas gdy przekazuje kilka gniazd, plików lub cokolwiek do jądra prosząc o: jeśli coś się w nich zmieni, niech wywołanie select () powróci. - A jądro, jako pan świata, wie, kiedy to się dzieje.

Wynikiem tego wywołania funkcji select () może być: nowe dane w gnieździe łączą się z X11, przyszedł pakiet do portu UDP, na którym nasłuchujemy itd. - To nie jest ani sygnał Qt, ani zdarzenie Qt, a Główna pętla Qt sama decyduje, czy zamienia świeże dane w jedno, drugie, czy też je ignoruje.

Qt może wywołać metodę (lub kilka), taką jak keyPressEvent (), skutecznie zamieniając ją w zdarzenie Qt. Lub Qt emituje sygnał, który w efekcie wyszukuje wszystkie funkcje zarejestrowane dla tego sygnału i wywołuje je jedna po drugiej.

Jedna różnica między tymi dwoma koncepcjami jest tutaj widoczna: slot nie ma głosowania nad tym, czy inne automaty zarejestrowane dla tego sygnału zostaną wywołane, czy nie. - Zdarzenia są bardziej jak łańcuch, a program obsługi zdarzeń decyduje, czy przerywa ten łańcuch, czy nie. Pod tym względem sygnały wyglądają jak gwiazda lub drzewo.

Zdarzenie może wyzwolić sygnał lub całkowicie przekształcić go w sygnał (wystarczy go wyemitować i nie wywoływać „super ()”). Sygnał można przekształcić w zdarzenie (wywołanie programu obsługi zdarzenia).

Co abstrahuje, co zależy od przypadku: clicked () - sygnał streszcza zdarzenia myszy (przycisk opuszcza się i ponownie podnosi bez zbytniego poruszania się). Zdarzenia klawiatury to abstrakcje z niższych poziomów (takie rzeczy jak 果 lub é to kilka naciśnięć klawiszy w moim systemie).

Może focusInEvent () jest przykładem odwrotności: mógłby użyć (a tym samym abstrakcyjnego) sygnału clicked (), ale nie wiem, czy faktycznie tak jest.

Robert Siemer
źródło
4
Uważam, że ta część: „slot nie ma głosowania nad tym, czy inne sloty zarejestrowane dla tego sygnału zostaną wywołane, czy nie” bardzo pouczające z powodu różnicy między sygnałami a wydarzeniami. Mam jednak podobne pytanie: czym są Wiadomości i jak są powiązane z sygnałami i zdarzeniami? (jeśli są spokrewnione). Czy komunikaty są abstrakcją sygnałów i zdarzeń? Czy można ich użyć do opisania takich interakcji między QObjects (lub innymi obiektami?)
user1284631
@axeoth: W Qt nie ma czegoś takiego jak „wiadomości”. Cóż, jest okno wiadomości, ale to wszystko.
Unslander Monica
@KubaOber: Dziękuję. Miałem na myśli „wydarzenia”.
user1284631
3
@axeoth: Zatem twoje pytanie jest bezsensowne. Brzmi: „czym są zdarzenia i jak są powiązane z sygnałami i zdarzeniami”.
Unslander Monica
@KubaOber: Nie pamiętam kontekstu rok później. W każdym razie wygląda na to, że pytałem prawie to samo co OP: jaka jest różnica między zdarzeniami i jak zdarzenia są powiązane z sygnałami i slotami. Tak naprawdę wtedy, IIRC, szukałem sposobu na zawinięcie klas sterowanych sygnałem / szczelinami Qt w jakieś klasy inne niż Qt, więc szukałem sposobu, aby sterować pierwszą z wnętrza drugiej. Wyobrażam sobie, że rozważałem wysyłanie do nich zdarzeń, ponieważ oznaczało to, że musiałem tylko dołączyć nagłówki Qt, a nie zmuszać moich klas do implementacji sygnału / gniazd.
user1284631
16

Zdarzenia są wysyłane przez pętlę zdarzeń. Każdy program GUI wymaga pętli zdarzeń, niezależnie od tego, co napiszesz Windows lub Linux, używając Qt, Win32 lub dowolnej innej biblioteki GUI. Każdy wątek ma również własną pętlę zdarzeń. W Qt „GUI Event Loop” (główna pętla wszystkich aplikacji Qt) jest ukryta, ale zaczynasz ją wywoływać:

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

Komunikaty i inne aplikacje wysyłane do programu są wysyłane jako zdarzenia.

Sygnały i sloty to mechanizmy Qt. W procesie kompilacji z wykorzystaniem moc (kompilator meta-obiektowy) są one zamieniane na funkcje zwrotne.

Wydarzenie powinno mieć jednego odbiorcę, który powinien je wysłać. Nikt inny nie powinien dostać tego wydarzenia.

Wszystkie sloty podłączone do emitowanego sygnału zostaną wykonane.

Nie powinieneś myśleć o sygnałach jako o zdarzeniach, ponieważ jak możesz przeczytać w dokumentacji Qt:

Kiedy sygnał jest emitowany, gniazda do niego podłączone są zwykle wykonywane natychmiast, tak jak normalne wywołanie funkcji. Kiedy tak się dzieje, mechanizm sygnałów i gniazd jest całkowicie niezależny od pętli zdarzeń GUI.

Kiedy wysyłasz zdarzenie, musi poczekać jakiś czas, aż pętla zdarzeń wywoła wszystkie zdarzenia, które nadeszły wcześniej. Z tego powodu wykonanie kodu po wysłaniu zdarzenia lub sygnału jest inne. Kod następujący po wysłaniu zdarzenia zostanie uruchomiony natychmiast. W przypadku mechanizmów sygnałów i gniazd zależy to od typu połączenia. Zwykle zostanie wykonane po wszystkich slotach. Używając Qt :: QueuedConnection, zostanie to wykonane natychmiast, podobnie jak zdarzenia. Sprawdź wszystkie typy połączeń w dokumentacji Qt .

firescreamer
źródło
To zdanie daje mi zwięzłe zrozumienie różnicy między slotem sygnałowym Qt a wydarzeniami: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

Jest artykuł, który szczegółowo omawia przetwarzanie zdarzeń: http://www.packtpub.com/article/events-and-signals

Omawia różnicę między zdarzeniami a sygnałami tutaj:

Zdarzenia i sygnały to dwa równoległe mechanizmy służące do osiągnięcia tego samego. Ogólna różnica polega na tym, że sygnały są przydatne podczas korzystania z widgetu, podczas gdy zdarzenia są przydatne podczas wdrażania widgetu. Na przykład, kiedy używamy widżetu takiego jak QPushButton, bardziej interesuje nas jego sygnał clicked () niż niskopoziomowe naciśnięcie myszy lub zdarzenia naciśnięcia klawisza, które spowodowały wyemitowanie sygnału. Ale jeśli implementujemy klasę QPushButton, bardziej interesuje nas implementacja kodu dla zdarzeń myszy i klawiszy. Ponadto zwykle obsługujemy zdarzenia, ale otrzymujemy powiadomienia o emisji sygnałów.

Wydaje się, że jest to powszechny sposób mówienia o tym, ponieważ przyjęta odpowiedź zawiera niektóre z tych samych zwrotów.


Uwaga, proszę zapoznać się z pomocnymi komentarzami poniżej tej odpowiedzi Kuby Obera, które sprawiają, że zastanawiam się, czy może to być trochę uproszczone.

eric
źródło
Nie rozumiem, jak byłyby to dwa mechanizmy używane do osiągnięcia tego samego - myślę, że to bezużyteczne uogólnienie, które nikomu nie pomaga.
Unslander Monica
@KubaOber nie, pomaga uniknąć szczegółów niższego poziomu. Czy powiedziałbyś, że Python nie jest pomocny, ponieważ możesz zrobić to samo, pisząc w kodzie maszynowym? :)
eric
2
Twierdzę, że pierwsze zdanie cytatu jest uogólniające, do tego stopnia, że ​​jest bezużyteczne. Technicznie nie jest to błędne, ale tylko dlatego, że jeśli chcesz, możesz użyć przekazywania zdarzeń, aby osiągnąć to, co robi mechanizm szczeliny sygnałowej i odwrotnie. Byłoby to bardzo uciążliwe. Więc nie, szczeliny sygnałowe nie są tym samym, co zdarzenia, nie osiągają tego samego, a fakt, że oba istnieją, ma kluczowe znaczenie dla sukcesu Qt. Podany przykład przycisku całkowicie ignoruje ogólną funkcjonalność systemu szczelin sygnałowych.
Unslander Monica
1
„Zdarzenia i sygnały to dwa równoległe mechanizmy służące do osiągnięcia tego samego w wąskim zakresie niektórych widżetów / elementów sterujących interfejsu użytkownika ”. Odważna część jest krytycznie pominięta i sprawia, że ​​cytat jest nieprzydatny. Nawet wtedy można wątpić, ile z tego „tego samego” zostało naprawdę osiągnięte: sygnały pozwalają reagować na zdarzenia kliknięcia bez instalowania filtru zdarzeń na widgecie (lub wyprowadzania go z widżetu). Robienie tego bez sygnałów jest znacznie bardziej kłopotliwe i ściśle łączy kod klienta z kontrolą. To zły projekt.
Unslander Monica
1
Wydarzenia są pojęciem wszechobecnym . Konkretna implementacja w Qt konkretnie ustawia je jako przekazane struktury danych event. Sygnały i szczeliny są konkretnie metodami, podczas gdy mechanizm połączenia jest strukturą danych, która pozwala sygnałowi wywołać jedną lub więcej szczelin wymienionych jako połączone z nią. Mam nadzieję, że widzicie, że mówienie o sygnale / szczelinach jako o jakimś „podzbiorze” lub „wariancie” wydarzeń jest nonsensem i na odwrót. Oni naprawdę są różne rzeczy, które zdarzają się być używany do podobnych celów w kontekście niektórych widżetów. Otóż ​​to. Im bardziej uogólniasz, tym mniej pomocny stajesz się IMHO.
Unslander Monica
5

TL; DR: Sygnały i szczeliny to pośrednie wywołania metod. Zdarzenia to struktury danych. Więc są to zupełnie inne zwierzęta.

Jedynym momentem, w którym się łączą, jest wykonywanie wywołań szczelin poza granicami wątku. Argumenty wywołania gniazda są pakowane w strukturę danych i wysyłane jako zdarzenie do kolejki zdarzeń wątku odbierającego. W wątku odbierającym QObject::eventmetoda rozpakowuje argumenty, wykonuje wywołanie i prawdopodobnie zwraca wynik, jeśli było to połączenie blokujące.

Jeśli jesteśmy skłonni uogólniać na zapomnienie, można by pomyśleć o zdarzeniach jako o sposobie wywołania metody obiektu docelowego event. W pewnym sensie jest to wywołanie metody pośredniej - ale nie sądzę, aby było to pomocne w myśleniu o tym, nawet jeśli jest to prawdziwe stwierdzenie.

Unslander Monica
źródło
2

Zdarzenia (w ogólnym sensie interakcji użytkownik / sieć) są zwykle obsługiwane w Qt za pomocą sygnałów / gniazd, ale sygnały / gniazda mogą robić wiele innych rzeczy.

QEvent i jego podklasy to w zasadzie tylko małe standardowe pakiety danych dla frameworka do komunikacji z kodem. Jeśli chcesz w jakiś sposób zwrócić uwagę na mysz, wystarczy spojrzeć na QMouseEvent API, a projektanci biblioteki nie muszą wymyślać koła na nowo za każdym razem, gdy musisz dowiedzieć się, co zrobiła mysz w jakimś rogu API Qt.

Prawdą jest, że jeśli czekasz na jakieś zdarzenia (znowu w ogólnym przypadku), Twój automat prawie na pewno zaakceptuje podklasę QEvent jako argument.

Mając to na uwadze, sygnały i szczeliny z pewnością mogą być używane bez QEvents, chociaż przekonasz się, że pierwotnym impulsem do aktywacji sygnału często będzie jakaś interakcja użytkownika lub inna asynchroniczna aktywność. Czasami jednak twój kod po prostu osiągnie punkt, w którym odpalenie określonego sygnału będzie właściwą rzeczą do zrobienia. Na przykład odpalenie sygnału podłączonego do paska postępu podczas długiego procesu nie obejmuje QEvent do tego momentu.

jkerian
źródło
2
„Zdarzenia są zwykle obsługiwane w Qt za pomocą sygnałów / szczelin” - w rzeczywistości nie ma… Obiekty QEvent są zawsze przesyłane przez przeciążone wirtualne! Na przykład w QWidget nie ma sygnału „keyDown” - zamiast tego keyDown jest funkcją wirtualną.
Stefan Monov
Zgadzam się ze Stefanem, właściwie dość zagmatwany kawałek Qt
Harald Scheirich
1
@Stefan: Twierdziłbym, że niewiele aplikacji Qt zastępuje keyDown (i zamiast tego używa głównie sygnałów takich jak QAbstractButton :: clicked i QLineEdit :: editFinished), aby uzasadnić „typowo”. Z pewnością wcześniej złapałem dane wejściowe z klawiatury, ale nie jest to zwykły sposób obsługi zdarzeń.
jkerian,
po edycji (wyjaśniającej, co rozumiesz przez „wydarzenie”), Twój post jest teraz poprawny. Powstrzymuję się jednak od ponownego używania takich słów. Sytuacja jest wystarczająco mętna bez nazywania sygnałów „rodzajem wydarzeń”.
Stefan Monov
2

Znalazłem to pytanie podczas czytania „Przetwarzania zdarzeń” Leow Wee Khenga. Mówi również:

wprowadź opis obrazu tutaj

Jasmine Blanchette mówi:

Głównym powodem, dla którego należy używać zdarzeń zamiast standardowych wywołań funkcji lub sygnałów i szczelin, jest to, że zdarzenia mogą być używane zarówno synchronicznie, jak i asynchronicznie (w zależności od tego, czy wywołujesz sendEvent (), czy postEvents ()), podczas wywoływania funkcji lub wywoływania gniazdo jest zawsze synchroniczne. Kolejną zaletą wydarzeń jest to, że można je filtrować.

francek
źródło
1

Kolejna drobna uwaga pragmatyczna: wysyłanie lub odbieranie sygnałów wymaga dziedziczenia, QObjectpodczas gdy obiekt dowolnego dziedziczenia może publikować lub wysyłać zdarzenie (ponieważ wywołujesz QCoreApplication.sendEvent()lub postEvent()) Zwykle nie jest to problem, ale: aby używać sygnałów PyQt dziwnie wymaga, QObjectaby być pierwszą superklasą, i możesz nie chcieć zmieniać kolejności dziedziczenia tylko po to, aby móc wysyłać sygnały).

bootchk
źródło
-1

Moim zdaniem wydarzenia są całkowicie zbędne i można by je wyrzucić. Nie ma powodu, dla którego sygnały nie mogłyby zostać zastąpione przez zdarzenia lub zdarzenia przez sygnały, z wyjątkiem tego, że Qt jest już ustawione tak, jak jest. Sygnały w kolejce są opakowane w zdarzenia, a zdarzenia mogą być opakowane w sygnały, na przykład:

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

Zastąpiłby wygodną mouseMoveEvent()funkcję znajdującą się w QWidget(ale QQuickItemjuż nie) i obsługiwałby mouseMovesygnały, które menedżer sceny emitowałby dla elementu. Fakt, że sygnał jest emitowany w imieniu przedmiotu przez jakąś zewnętrzną jednostkę jest nieistotny i zdarza się dość często w świecie komponentów Qt, chociaż podobno jest to niedozwolone (komponenty Qt często omijają tę zasadę). Ale Qt to konglomerat wielu różnych decyzji projektowych i prawie rzucony w kamień ze strachu przed złamaniem starego kodu (co i tak zdarza się dość często).

user1095108
źródło
Zdarzenia mają tę zaletę QObject, że w razie potrzeby propagują hierarchię nadrzędny-podrzędny. Połączenia sygnału / gniazda są po prostu obietnicą wywołania funkcji, bezpośrednio lub pośrednio, gdy zostanie spełniony określony warunek. Nie ma powiązanej hierarchii obsługi z sygnałami i gniazdami.
anonimowy
Możesz zaimplementować podobne zasady propagacji z sygnałami. Nie ma reguły. że określonego sygnału nie można ponownie wysłać do innego obiektu (dziecka). Możesz dodać acceptedparametr odniesienia do sygnału i gniazd obsługujących go lub możesz mieć strukturę jako parametr odniesienia z acceptedpolem. Ale Qt dokonał wyborów projektowych, które podjęła i są teraz ustalone w kamieniu.
user1095108
1
Po prostu reimplementujesz zdarzenia, jeśli robisz to w sposób sugerowany.
Fabio A.
@FabioA. O to chodzi w pytaniu PO. Zdarzenia i sygnały mogą / mogą się wzajemnie zastępować.
user1095108
Jeśli ponownie zaimplementujesz wydarzenia, nie zastępujesz wydarzeń. Co więcej: sygnały są wdrażane na szczycie wydarzeń. Potrzebujesz pewnego rodzaju "systemu zdarzeń", aby powiedzieć innym pętlom zdarzeń, być może w wątku, który nie jest twój, że kiedyś w przyszłości będzie musiał gdzieś wykonać daną funkcję.
Fabio A.