[Kurs QT] Sygnały i sloty

Nieco więcej o sygnałach i slotach, a także o komunikacji pomiędzy oknami utworzonymi w 1 programie.

Wstęp


W tej lekcji dowiesz się czym jest system sygnałów i slotów, jak działa, a także jak napisać własną klasę, która będzie w stanie korzystać z tego systemu.

To jest druga wersja tej lekcji, jeżeli szukasz starszej gdzie pokazałem sygnały i sloty na przykładzie edytora tekstu zawierające własne okno narzędzi to zachęcam cię do pobrania html starej wersji.

 

Sygnały i sloty – a komu to potrzebne?


Jeżeli wcześniej korzystałeś z jakiejś biblioteki okienkowej lub np. SFML to prawdopodobnie wiesz, że każda akcja wykonana na oknie (np. wciśnięcie przycisku) generuje pewne zdarzenie tzw. event, który programista może przechwycić i nadać mu jakąś akcję (np. zamknięcie programu).

W Qt do generowania i odbierania takich zdarzeń służą właśnie sygnały i sloty połączone magiczną funkcją connect (można też korzystać z makr, których będziemy używali nagminnie w kolejnych lekcjach, jednak dużo lepiej jest korzystać z connect).

Zgodnie z intuicją sygnały to są właśnie zdarzenia emitowane przez jakiś obiekt, z kolei sloty to funkcje, które przechwytują dany sygnał i wykonują po jego odebraniu określone operacje.

Co ważne sygnały, mogą być połączone tylko z metodami zadeklarowanymi jako sloty (o tym później) i do jednego sygnału może być przypisanych wiele slotów. Aby zobaczyć jakie sygnały emitują dane kontrolki, czy też jakie posiadają sloty należy wejść na stronę dokumentacji danej klasy.

Łączenie sygnałów i slotów zachodzi przy użyciu wspomnianej wcześniej funkcji connect(…):

Przyjrzyjmy się nieco tej funkcji:

Pierwszym argumentem jest adres (wskaźnik) do obiektu, który nadaje sygnał, tzn jeśli chcemy połączyć wciśnięcie przycisku z funkcją to tutaj podajemy adres do tego przycisku.

Drugim argumentem jest sygnał, który jest emitowany przez obiekt emitujący sygnał, zwróć uwagę na składnię: sam rodzaj sygnału wygląda jak wywołanie zwykłej funkcji, lecz jest w klauzuli SIGNAL(…).

Trzecim obiektem jest adres do obiektu, w którym możemy znaleźć slot reagujący na sygnał, tzn jeśli znajduje się w tej samej klasie co użycie connect (co najczęściej się zdarza) to po prostu tutaj wstawimy this .

Czwartym argumentem jest slot (czyli po prostu metoda), która zostanie uruchomiona po wyemitowaniu sygnału. Podobnie jak wcześniej sama funkcja jest w specjalnej klauzuli, tym razem SLOT(…).

Sygnały i sloty mogą posiadać argumenty, w ten łatwy sposób można przekazywać zmienne do slotu, należy jednak pamiętać że sygnały i sloty muszą przyjmować takie same typy argumentów w tej samej kolejności.

Własne sygnały i sloty


Aby móc stworzyć, a następnie połączyć sygnały i sloty w stworzonej przez nas klasie to musi ona dziedziczyć w sposób pośredni lub bezpośredni po klasie QObject, musi także posiadać makro Q_OBJECT na samym początku pliku nagłówkowego klasy.

Sygnały

Własne sygnały należy zadeklarować pod klauzulą widoczności signals, które działa analogicznie jak public, z tym że sygnały nie posiadają ciała funkcji i są zawsze typu void .

Sygnały mogą być tylko i wyłącznie emitowane, służy do tego słowo kluczowe emit, można skojarzyć sobie że działa podobnie jak return , lecz należy pamiętać, że nie zastępuje go! Co oznacza, że po użyciu emit jeżeli dalej są jakieś instrukcje to zostaną one wykonane!

 

Sloty

Z kolei sloty są bardziej podobne do tradycyjnych metod, posiadają własne ciało i mogą być używane jak zwykłe metody, co oznacza, że mogą być wywoływane jako zwykłe metody przez dowolną funkcję. Podobnie jak sygnały tak i sloty mogą być tylko typu void .

Aby jakaś metoda stała się sygnałem to musi zostać zadeklarowana pod operatorem: <operator widoczności> slots, gdzie <operator widoczności> to ten znany nam z tradycyjnego c++, np możemy użyć private slots, wtedy sloty będą widoczne tylko dla naszej klasy.

Jeżeli ktoś jest ciekawy przykładu to odsyłam albo do archiwalnego wpisu (gdzie program jest w sumie dość zaawansowany), albo do kolejnych lekcji gdzie używam tego mechanizmu w niespecjalnie skomplikowany sposób (np o multimediach).

[GitHub]

Code ON!