2016-07-28 18 views
1

ボタンが押されている時間を確認する方法を探しています!私の考えは、pressed()が発射され、released()が発射されたときに始まるカウンターを開始していた。しかし、私は現在、リリースされたイベントまたは同様のイベントを待つ方法を知らない。通常、私はconnect()スロットを持つ信号ですが、この場合は両方ともスロットです。たぶんあなたは良い考えがあるかもしれません。ボタンが押されている時間を確認する方法は?

答えて

4

pressed。タイマーを開始する。 releasedタイマーが実行されている時間をチェックして停止します。経過時間をクラスの変数に保存します。

これは少なくともそれを行う方法の1つです。

+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" 

あなたは本当に他のコードに結合されていない場合でも、コントローラは、まだコードの残りの部分のデザインに多少依存していることを叫ぶことができます。ありがたいことに、それはそうである必要はありません:ラムダは単純な適応を簡単にします。

我々はあまりにも、私たちの大企業のベンダーが提供する「外来」のコントローラを、使用することができます。上記の例のすべてがコンパイル可能です

// 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

1つの質問:2つの信号を互いに接続すると、その機能は何ですか?それは私が推測するものです:それはチェーンのように動作します。一方の信号は他方の信号を放射し、他方の信号は接続されたスロットを作動させる。 – tistCoder

+1

@tistCoder呼び出し可能なものには、メソッドやファンクタなどのシグナルを接続できます。信号を信号に接続するということは、第1の信号が放射されると第2の信号が呼び出され(したがって放出される)ことを意味する。シグナルは単にモックで生成されたメソッドであることを覚えておいてください。 –

+0

あなたの答えをありがとう。今私は以前よりずっと多くを知っています – tistCoder

関連する問題