2015-02-15 9 views
13

Łączę gniazdo z sygnałem. Ale teraz chcę je tymczasowo odłączyć.Jak tymczasowo rozłączyć sygnał z gniazdem w Qt?

Tutaj jest częścią mojego deklaracji klasy:

class frmMain : public QWidget 
{ 
    ... 
private: 
    QTimer *myReadTimer; 
    ... 
private slots: 
    void on_btnDownload_clicked(); 
    ... 
}; 

w konstruktorze frmMain, łączę myReadTimer z gniazda, tak aby ReadMyCom będzie wywoływana co 5 sekund:

myReadTimer=new QTimer(this); 
myReadTimer->setInterval(5000); 
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom())); 

Ale w gnieździe on_btnDownload_clicked. Nie chcę, aby myReadTimer emitował dowolny sygnał w zakresie on_btnDownload_clicked. Dlatego chcę je odłączyć na początku on_btnDownload_clicked i ponownie podłączyć je na końcu. Tak:

void frmMain::on_btnDownload_clicked() 
{ 
    //some method to disconnect the slot & singal 

    ...//the code that I want myReadTimer to leave me alone 

    //some method to reconnect the slot & singal 
} 

Szukałem w Stackoverflow i dostaliśmy odpowiedź jak wywołać QObject destruktora. Ale nie wiem, jak z niego korzystać.

Próbowałem również użyć disconnect, jak:

QMetaObject::Connection myConnect; 
myConnect=connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom())); 
... 
disconnect(& myConnect); 

Ale to nadal nie działa. Czy ktoś może mi pomóc, jak to zrobić?

+1

Czy obejrzysz dokumentacji 'disconnect'? Ma takie same parametry jak "connect". –

+0

Przeczytałem dokument odłączenia i odnalazłem 'static bool disconnect (const QMetaObject :: Connection &); 'Jak więc się myliłem? – ctxrr

Odpowiedz

6

odłączyć/podłączyć składnia

Istnieje wiele sposobów, aby zadzwonić odłączyć, w zależności od tego, co dokładnie chcesz odłączony. Zobacz the QObject documentation page, aby dowiedzieć się, jak działają.

Oto przykład użycia wartości 0 do "odłączenia wszystkich gniazd".

void frmMain::on_btnDownload_clicked() 
{ 
    // disconnect everything connected to myReadTimer's timeout 
    disconnect(myReadTimer, SIGNAL(timeout()), 0, 0);  

    ...//the code that I want myReadTimer to leave me alone 

    // restore the connection 
    connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom())); 
} 

Albo można określić dokładną parę sygnał gniazda, aby odłączyć kopiując składnię „Connect”, podobnie jak to:

disconnect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom())); 

Zatrzymywanie timera

Skoro pracujesz licznik czasu, może to być prostsze:

Różnice w stosunku do oryginalnego podejścia:

  • Od czasu zatrzymania i ponownego uruchomienia zegara, następnym razem, gdy zostanie uruchomiony, będzie interval po zakończeniu funkcji gniazda.

Czy musisz w ogóle robić coś wyjątkowego?

W aplikacji jednowątkowej Qt, jeśli już przetwarzasz sygnał, inny sygnał nie "przeskoczy w środku" tego kodu. Zamiast tego będzie ustawiona w kolejce jako opcja do obsługi natychmiast po przywróceniu bieżącego gniazda.

Być może nie trzeba w ogóle zatrzymywać ani odłączać zegara.

Różnice z oryginalnego podejścia:

  • Jeśli on_btnDownload_clicked zajmuje trochę czasu, aby wykonać, może mieć wiele ReadMyCom zdarzenia w kolejce po on_btnDownload_clicked uzupełnia. (Zauważ, że w tym momencie będziesz miał operację, która i tak "zamknie" twój GUI na jakiś czas, może mieć więcej sensu refaktoryzacja funkcji lub nadanie jej własnego wątku.)
16

bardzo dobra funkcja w QObject, która przydaje się od czasu do czasu: QObject::blockSignals()

Oto bardzo prosta klasa, która zrobi to, co chcesz. I nie biorą kredyt na to konstrukcja, znalazłem go w internecie gdzieś dawno temu. Bądź jednak ostrożny, zablokuje wszystkie sygnały do ​​wszystkich obiektów. Jeśli tego nie chcesz, możesz zmodyfikować klasę zgodnie ze swoimi potrzebami.

class SignalBlocker{ 
public: 
    SignalBlocker(QObject *o): object(o), alreadyBlocked(object->signalsBlocked()){ 
     if (!alreadyBlocked){ 
      object->blockSignals(true); 
     } 
    } 
    ~SignalBlocker() { 
     if (!alreadyBlocked){ 
      object->blockSignals(false); 
     } 
    } 

private: 
    QObject *object; 
    bool alreadyBlocked; 
}; 

użycia, w przypadku, staje się trywialne

void frmMain::on_btnDownload_clicked() 
{ 
    SignalBlocker timerSignalBlocker(myReadTimer); 

    ...//the code that I want myReadTimer to leave me alone 

    // signals automatically unblocked when the function exits 
} 

UPDATE:

widzę, że z Qt 5.3, bardzo podobna klasa została oficjalnie dodany do API. Działa podobnie jak wyżej z nieco większym zestawem funkcji. Proponuję zamiast użyć oficjalnego klasę QSignalBlocker w celu utrzymania codebase się na bieżąco ze wszelkimi zmianami API.

Wykorzystanie pozostaje jednak taka sama.

Powiązane problemy