2016-07-28 55 views
1

我正在尋找一種方法來檢查一個按鈕被按下多久!我的想法是啓動一個計數器,該計數器在pressed()發射時開始,並在發射released()時停止。但我目前不知道如何等待發布的或類似的事件。通常我會給connect()帶插槽的信號,但在這種情況下都是插槽。也許你有一個更好的主意,也許這個是足夠好的。如何檢查按鈕按下的時間?

回答

4

當時pressed。啓動一個計時器。當released檢查定時器運行了多久(並停止它)。將經過的時間保存在類中的變量中。

這是至少做到這一點的一種方法。

+1

感謝您的回答!我一直在考慮這一點,但我不知道如何保存其他方法/插槽的起點......我忘了一個類的基本屬性:一個簡單的成員變量 - , - – tistCoder

4

pressed信號發送時,啓動定時器。當發送relesed信號時,請閱讀定時器已經過了多長時間。

這是使用Qt 5一個完整的示例和C++編譯器,這不是史前:

// https://github.com/KubaO/stackoverflown/tree/master/questions/button-timer-38645219 
#include <QtWidgets> 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    QWidget w; 
    QFormLayout layout{&w}; 
    QPushButton button{"Press Me"}; 
    QLabel label; 
    layout.addRow(&button); 
    layout.addRow(&label); 

    QElapsedTimer timer; 
    QObject::connect(&button, &QPushButton::pressed, [&]{ timer.start(); }); 
    QObject::connect(&button, &QPushButton::released, [&]{ 
     label.setText(QStringLiteral("Pressed for %1 ms").arg(timer.elapsed())); 
    }); 
    w.show(); 
    return app.exec(); 
} 

當然你也可以推所有變量爲一類。您會注意到C++ 11使得這種轉換幾乎毫無疑問:它是設計而非巧合。

#include <QtWidgets> 

class Widget : public QWidget { 
    QFormLayout layout{this}; 
    QPushButton button{"Press Me"}; 
    QLabel label; 
    QElapsedTimer timer; 
public: 
    Widget() { 
     layout.addRow(&button); 
     layout.addRow(&label); 

     connect(&button, &QPushButton::pressed, [&]{ timer.start(); }); 
     connect(&button, &QPushButton::released, [&]{ 
     label.setText(QStringLiteral("Pressed for %1 ms").arg(timer.elapsed())); 
     }); 
    } 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    Widget w; 
    w.show(); 
    return app.exec(); 
} 

人們普遍不贊成以在UI對象「商業邏輯」,所以我們可以在此功能中分離出來成爲一個Timer的,一個Widget和的Controller。所有這些對象外部的代碼都建立了必要的連接。

#include <QtWidgets> 

class Timer : public QObject { 
    Q_OBJECT 
    QElapsedTimer timer; 
public: 
    Q_SLOT void start() { timer.start(); } 
    Q_SLOT void stop() { emit elapsed(timer.elapsed()); } 
    Q_SIGNAL void elapsed(qint64); 
}; 

class Widget : public QWidget { 
    Q_OBJECT 
    QFormLayout layout{this}; 
    QPushButton button{"Press Me"}; 
    QLabel label; 
public: 
    Widget() { 
     layout.addRow(&button); 
     layout.addRow(&label); 
     connect(&button, &QPushButton::pressed, this, &Widget::pressed); 
     connect(&button, &QPushButton::released, this, &Widget::released); 
    } 
    Q_SIGNAL void pressed(); 
    Q_SIGNAL void released(); 
    Q_SLOT void setText(const QString & text) { label.setText(text); } 
}; 

class Controller : public QObject { 
    Q_OBJECT 
public: 
    Q_SLOT void elapsed(qint64 ms) { 
     emit hasText(QStringLiteral("Pressed for %1 ms").arg(ms)); 
    } 
    Q_SIGNAL void hasText(const QString &); 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    Timer t; 
    Widget w; 
    Controller c; 
    w.show(); 
    // 
    QObject::connect(&w, &Widget::pressed, &t, &Timer::start); 
    QObject::connect(&w, &Widget::released, &t, &Timer::stop); 
    QObject::connect(&t, &Timer::elapsed, &c, &Controller::elapsed); 
    QObject::connect(&c, &Controller::hasText, &w, &Widget::setText); 
    return app.exec(); 
} 
#include "main.moc" 

當然,你可以尖叫控制器,即使沒有真正連接到其他的代碼,仍然一定程度上取決於代碼的其餘部分的設計。幸運的是,它不一定如此:lambda使簡單的適應變得簡單。

我們可以用一個「洋」控制器,通過我們的大企業供應商提供的,太:

// use Timer and Widget from preceding example 
#include <sstream> 
#include <string> 
#include <functional> 

class Controller { 
public: 
    using callback_t = std::function<void(const std::string&)>; 
    Controller(callback_t && callback) : callback{std::move(callback)} {} 
    void onElapsed(int ms) { 
     std::stringstream s; 
     s << "Pressed for " << ms << " ms"; 
     callback(s.str()); 
    } 
private: 
    callback_t callback; 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    Timer t; 
    Widget w; 
    Controller c{ [&](const std::string & s){ w.setText(QString::fromStdString(s)); } }; 

    QObject::connect(&w, &Widget::pressed, &t, &Timer::start); 
    QObject::connect(&w, &Widget::released, &t, &Timer::stop); 
    QObject::connect(&t, &Timer::elapsed, [&](qint64 ms) { c.onElapsed(ms); }); 
    w.show(); 
    return app.exec(); 
} 
#include "main.moc" 

所有以上的例子是可編譯:把它們中的任何一個進入main.cpp,重建項目,走。

當你發佈測試用例的問題時,你應該倒退:你從這個答案的末尾開始,開始工作,最小化安裝。它會幫助你更好地理解你自己的代碼,因爲冗長度最小化。這是說,我希望,第一個和最後一個版本都具有相同的功能。

+0

一個問題:如果你連接2個信號,它是什麼功能?這就是我猜測的:它像一個鏈條一樣工作。一個信號發出另一個信號,那個信號激活連接的插槽。 – tistCoder

+1

@tistCoder您可以將信號連接到任何可調用的方法:方法或函子。將信號連接到信號意味着當第一個信號被髮射時,第二個信號被調用(並因此被髮射)。請記住,信號只是moc生成的方法。 –

+0

感謝您的回答。現在我比以前知道更多 – tistCoder

相關問題