Paź 24 2009

Qt Tips'n'Tricks: zwracanie wartości przez sloty

Kategorie: Programowanie Qt Qt Tips & Trics Techblog Matthew @ 01:46:30

Czasami zachodzi taka potrzeba, że chcemy aby slot nam coś zwrócił do miejsca w którym został wyemitowany sygnał do którego ten slot jest podpięty. Ponieważ same sloty są typu void więc trzeba to obejść inną drogą.

Sloty i sygnały (z punktu widzenia C++) są zwykłymi metodami. Sygnał dzięki przeprocesorowi Qt jest obrabiany do metody wowołująceć sloty (lub inne sygnały). Więc czemu nie skorzystać z przekazywania wartości przez parametry do zwracania wartości przez slot do sygnały, a z sygnału do miejsca w którym potrzebujemy wartości obrabianych przez slot? Oto rozwiązanie:

naszaklasa.hpp:

  1. #ifndef NASZAKLASA_HPP
  2. #define NASZAKLASA_HPP
  3.  
  4. #include <QObject>
  5.  
  6. class NaszaKlasa : public QObject
  7. {
  8.          Q_OBJECT
  9.  
  10. public:
  11.          NaszaKlasa();
  12.          ~NaszaKlasa();
  13.  
  14.          void foo();
  15.  
  16. public slots:
  17.          void mojSlot(QString & wyjscie, QString wejscie);
  18.  
  19. signals:
  20.          void mojSygnal(QString & wyjsce, QString wejscie);
  21. };
  22.  
  23. #endif // MAINWINDOW_HPP
  24.  

naszaklasa.cpp:

  1. #include "mainwindow.hpp"
  2.  
  3. #include <iostream>
  4.  
  5. using namespace std;
  6.  
  7. NaszaKlasa::NaszaKlasa()
  8. {
  9.  
  10.          connect(this, SIGNAL(mojSygnal(QString&,QString)), this, SLOT(mojSlot(QString&,QString)));
  11.  
  12.          foo();
  13. }
  14.  
  15. NaszaKlasa::~NaszaKlasa()
  16. {
  17. }
  18.  
  19. void NaszaKlasa::foo()
  20. {
  21.         QString dane = "test";
  22.         QString out;
  23.         emit mojSygnal(out, dane);
  24.  
  25.         cout << out.toStdString() << endl;
  26. }
  27.  
  28. void MainWindow::mojSlot(QString &wyjscie, QString wejscie)
  29. {
  30.         wyjscie = wejscie + " 123";
  31. }
  32.  

Całość opiera się na podstawowej własności każdego nowoczesnego jezyka, czyli przekazywaniu parametrów do funkcji poprzez referencję. Zarówno sygnał jak i slot mają po jednym argumencie "wyjściowym" który jest zmienną referencyjną, przez którą przekazujemy dane ze slotu do metody w której wyemitowaliśmy sygnał.

Wadą takiego rozwiązania jest to, że podpięcie jednego sygnały do wielu slotów powoduje że zmienna do której ma pójść wyjście zawiera tylko wartość ze slotu który został podpięty jako ostatni. Choć i ten przypadek można by rozwiązać poprzez ustawienie typu takiej zmiennej jako listy lub mapy.

Komentarze:

  1. salmon:

    Nie podoba mi się takie podejście. Ja bym w slocie po prostu wemitował sygnał ze zmienionymi danymi.

  2. Matthew:

    @salmon: moje podejście jest znacznie lepsze niż Ci się wydaje. Po pierwsze, to jest bardzo powszechne i zalecane w programowaniu. Funkcje, w normalny sposób, powinny zwracać tylko typy podstawowe, całą resztę albo przez referencję albo przez wskaźniki.
    Dalej dochodzi narzut jaki sobie robisz gdy musisz sprawdzić dla jakich danych wejściowych przychodzą wyjściowe z Twojego wyemitowanego sygnały. Same straty.

  3. mh:

    > Czasami zachodzi taka potrzeba, że chcemy aby slot nam coś zwrócił do miejsca w którym został wyemitowany
    > sygnał do którego ten slot jest podpięty.

    http://lists.trolltech.com/qt-interest/2002-08/thread00001-0.html

  4. naur:

    Jeszcze jedna uwaga. Ten sposób jest bezpieczny tylko w sytuacji gdy sygnał jest przesyłany w obrębie 1 wątku.

Dodaj komentarz: