2013-08-14 24 views
12

hinzuzufügen, habe ich zur Zeit ein Verfahren, welcheswie eine Verzögerung von 1 Sekunde unter Verwendung QTimer

void SomeMethod(int a) 
{ 

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

    //After one sec 
    SomeOtherFunction(a); 
} 

Dieses Verfahren ist tatsächlich ein Schlitz wie folgt ist, die auf ein Signal angeschlossen ist. Ich möchte eine Verzögerung von einer Sekunde mit Qtimer hinzufügen. Ich bin mir jedoch nicht sicher, wie dies zu erreichen ist. Da der Timer ein Signal auslöst, wenn er beendet ist, muss das Signal an eine andere Methode angehängt werden, die keine Parameter aufnimmt. Irgendein Vorschlag, wie ich diese Aufgabe erfüllen könnte.

Update: Das Signal wird mehrere Male in einer Sekunde aufgerufen und die Verzögerung wird für eine Sekunde sein. Mein Problem hier besteht darin, einen Parameter an den Slot zu übergeben, der an das timeout() Signal eines Timers angeschlossen ist. Meine letzte Annäherung würde sein, den Wert in einer Membervariable einer Klasse zu speichern und dann einen Mutex zu benutzen, um ihn davor zu schützen, geändert zu werden, während die Variable benutzt wird. Ich suche jedoch nach einfacheren Methoden hier.

+0

Erwarten Sie, Signale öfter zu verarbeiten als die Verzögerungszeit? – Linville

+0

@Linville Ja Meine Verzögerung wäre eine Sekunde und die Signale könnten mehrere Male in einer Sekunde – Rajeshwar

Antwort

1

Ich bin ein wenig verwirrt durch die Art, wie Sie Ihre Frage formulieren, aber wenn Sie fragen, wie das Timeout() Signal des Timers eine Funktion mit einem Parameter aufrufen, dann können Sie einen separaten Steckplatz zum Empfangen erstellen das Timeout und dann die gewünschte Funktion aufrufen. Etwas wie folgt aus: -

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; 

}; 

Implementierung: -

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); 
} 

Beachten Sie, dass die QObject Klasse hat tatsächlich einen Timer, der Sie durch den Aufruf von starttimer() verwenden können, so dass Sie nicht wirklich verwenden müssen ein separates QTimer-Objekt hier. Es ist hier enthalten, um zu versuchen, den Beispielcode nahe an der Frage zu halten.

+0

aufgerufen werden Ich sehe, dass Sie eine Mitgliedsvariable einer Klasse verwenden und den Parameter speichern. Dies wird jedoch Multithread sein. Also wird dieser Weg sicher sein? – Rajeshwar

+0

Ich würde nur diese Lösung einräumen, dass, wenn SomeMethod (..) schneller als einmal pro Sekunde aufgerufen wird, der Wert von m_a gequetscht wird, bevor es verwendet werden kann. – Linville

+0

Es kann sein, je nachdem, wie Sie es verwenden. Wenn Sie die Elementvariable in verschiedenen Threads festlegen und abrufen, stellen Sie sicher, dass Sie QMutex verwenden, um sie vor dem Festlegen/Abrufen zu sperren. Wenn Sie den Wert zwischen den Threads übergeben, können Sie über den Signal-Slot-Mechanismus sicherstellen, dass die Threads sicher sind. – TheDarkKnight

1

Wenn Sie anrufen SomeMethod mehrere Male pro Sekunde und die Verzögerung immer konstant, könnte man die Parameter a auf ein QQueue setzen und einen einzigen Schuss Timer erstellen SomeOtherFunction für den Aufruf, das die Parameter aus den QQueue bekommt.

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

Eigentlich gibt es eine viel elegante Lösung auf Ihre Frage, die nicht Mitglied Variablen oder Warteschlangen erfordert. Mit Qt 5.4 und C++ 11 können Sie run a Lambda expression right from the QTimer::singleShot(..) method! Wenn Sie Qt 5.0 - 5.3 verwenden, können Sie die Methode connect zu connect the QTimer's timeout signal to a Lambda expression verwenden, die die Methode aufruft, die mit dem entsprechenden Parameter verzögert werden muss.

Bearbeiten: Mit der Qt 5.4 Release ist es nur eine Zeile Code!

Qt 5.4 (und höher)

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

Qt Bewertung: 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

Das ist ganz nett. Schade, dass Sie den Lambda-Ausdruck nicht mit statischem 'QTimer :: singleShot()' verwenden können. –

+0

@Roku, einverstanden! Es ist [QTBUG-26406] (https://bugreports.qt-project.org/browse/QTBUG-26406). Hoffentlich werden sie es bald ansprechen! – Linville

+0

Auch verwende ich nicht C++ 11 – Rajeshwar

0

, das nicht funktioniert, weil QTimer::start nicht blockiert.

Sie sollten den Timer mit QTimer::singleShot starten und an einen Steckplatz anschließen, der nach dem Timeout des QTimers ausgeführt wird.