signal-slot

[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!

 


  • Michał

    Jak to jest z tym linkowaniem statycznym, jak to się robi? Jest już parę poradników na ten temat, ale każdy przestarzały. Moja wersja Qt to 5.4 z msvc

    • A masz płatną licencję? O ile dobrze się orientuję to linkowanie statyczne nie jest do końca zgodne z darmową licencją.

      Wracając do twojego pytania to nie bawiłem się w linkowanie statyczne, więc obecnie nie jestem w stanie ci pomóc, ale może ten film ci pomoże: https://youtu.be/Oyb20BAgx0U

  • Marian Kb

    Czy pisząc tutaj o slotach nie miałeś na myśli sygnałów? Chyba, że to ja nie ogarniam tematu.

    „Sloty polecam traktować jak funkcje (czy metody) typu void (nie mogą być innego typu), muszą być zadeklarowane w klasie pod słowem kluczowym slots:. Mogą mieć argumenty, ale nie muszą. Jeżeli mają przekazywać jakąś wartość do slotu to muszą ją mieć w nawiasie void fontSizeChanged(int) a także slot musi przyjmować argumenty tego samego typu np. void onFontSizeChanged(int) w przeciwnym razie program się nie skompiluje.”

    • Tak, dzięki. Powinno być: „jeżeli mają przekazywać jakąś wartość do sygnału…”