2013-08-14 21 views
12

momento ho un metodo che è la seguentecome aggiungere un ritardo di 1 secondo usando Qtimer

void SomeMethod(int a) 
{ 

    //Delay for one sec. 
    timer->start(1000); 

    //After one sec 
    SomeOtherFunction(a); 
} 

Questo metodo è in realtà una fessura che è collegato ad un segnale. Vorrei aggiungere un ritardo di un secondo usando Qtimer. Tuttavia non sono sicuro su come farlo. Poiché il timer attiva un segnale quando è finito e il segnale dovrebbe essere collegato a un altro metodo che non contiene alcun parametro. Qualche suggerimento su come potrei realizzare questo compito?

Aggiornamento: Il segnale verrà chiamato più volte in un secondo e il ritardo sarà per un secondo. Il mio problema qui è passare un parametro allo slot collegato al segnale di timeout() di un timer. Il mio ultimo approccio sarebbe quello di memorizzare il valore in una variabile memeber di una classe e quindi utilizzare un mutex per proteggerlo dalla modifica mentre la variabile viene utilizzata. In ogni caso, sto cercando metodi più semplici qui.

+0

Si prevede di gestire i segnali più spesso del periodo di ritardo? – Linville

+0

@Linville Sì Il mio ritardo sarebbe di un secondo ei segnali potrebbero essere chiamati più volte in un secondo – Rajeshwar

risposta

1

Sono un po 'confuso dal modo in cui si formula la domanda, ma se si sta chiedendo come ottenere il segnale di timeout() del timer per chiamare una funzione con un parametro, è possibile creare uno slot separato per ricevere il timeout e quindi chiamare la funzione desiderata. Qualcosa di simile a questo: -

class MyClass : public QObject 
{ 
    Q_OBJECT 

public: 
    MyClass(QObject* parent); 

public slots: 

    void TimerHandlerFunction(); 
    void SomeMethod(int a); 

private: 
    int m_a; 
    QTimer m_timer; 

}; 

Implementazione: -

MyClass::MyClass(QObject* parent) 
    :QObject(parent) 
{ 
    // connect the timer's timeout to our TimerHandlerFunction 
    connect(&m_timer, SIGNAL(timout()), this, SLOT(TimerHandlerFunction())); 
} 

void MyClass::SomeMethod(int a) 
{ 
    m_a = a; // store the value to pass later 

    m_timer.setSingleShot(true); // if you only want it to fire once 
    m_timer.start(1000); 
} 

void MyClass::TimerHandlerFunction() 
{ 
    SomeOtherFunction(m_a); 
} 

Nota che la classe QObject in realtà ha un timer che è possibile utilizzare chiamando startTimer(), quindi in realtà non ha bisogno di usare un oggetto QTimer separato qui. È incluso qui per cercare di mantenere il codice di esempio vicino alla domanda.

+0

Vedo che si sta utilizzando una variabile membro di una classe e si memorizza il parametro. Tuttavia questo sarà multithreaded. Quindi in questo modo sarai al sicuro? – Rajeshwar

+0

Vorrei solo sottolineare questa soluzione che se SomeMethod (..) viene chiamato più veloce di una volta al secondo, il valore di m_a verrà schiacciato prima di poter essere utilizzato. – Linville

+0

Può essere, a seconda di come lo si usa. Se si imposta e si ottiene la variabile membro in thread diversi, assicurarsi di utilizzare QMutex per bloccarlo prima di impostare/ottenere. Se stai passando il valore tra i thread, fare questo tramite il meccanismo dello slot del segnale assicurerà che sia thread-safe. – TheDarkKnight

1

Se si chiama SomeMethod più volte al secondo e il ritardo è sempre costante, si potrebbe mettere il parametro a ad un QQueue e creare un unico timer colpo per chiamare SomeOtherFunction, che ottiene il parametro dal QQueue.

void SomeClass::SomeMethod(int a) 
{ 
    queue.enqueue(a); 
    QTimer::singleShot(1000, this, SLOT(SomeOtherFunction())); 
} 

void SomeClass::SomeOtherFunction() 
{ 
    int a = queue.dequeue(); 
    // do something with a 
} 
43

In realtà, c'è un modo molto più soluzione elegante alla tua domanda che non necessita di variabili membro o code. Con Qt 5.4 e C++ 11 puoi run a Lambda expression right from the QTimer::singleShot(..) method! Se si utilizza Qt 5.0 - 5.3, è possibile utilizzare il metodo di connessione su connect the QTimer's timeout signal to a Lambda expression che chiamerà il metodo che deve essere ritardato con il parametro appropriato.

Modifica: Con la versione Qt 5.4 è solo una riga di codice!

Qt 5.4 (e versioni successive)

void MyClass::SomeMethod(int a) { 
    QTimer::singleShot(1000, []() { SomeOtherFunction(a); }); 
} 

Qt 5,0 - 5,3

void MyClass::SomeMethod(int a) { 
    QTimer *timer = new QTimer(this); 
    timer->setSingleShot(true); 

    connect(timer, &QTimer::timeout, [=]() { 
    SomeOtherFunction(a); 
    timer->deleteLater(); 
    }); 

    timer->start(1000); 
} 
+0

Questo è abbastanza bello. Peccato che non si possa usare l'espressione lambda con 'QTimer :: singleShot()' statico. –

+0

@Roku, d'accordo! È [QTBUG-26406] (https://bugreports.qt-project.org/browse/QTBUG-26406). Speriamo che lo affrontino presto! – Linville

+0

Anche io non sto usando C++ 11 – Rajeshwar

0

che non funziona perché QTimer::start non stia bloccando.

È necessario avviare il timer con QTimer::singleShot e collegarlo a uno slot che verrà eseguito dopo il timeout di QTimer.

Problemi correlati