如何检查按钮的按下时间?

时间:2016-07-28 19:31:20

标签: c++ qt

我正在寻找一种检查按钮按下时间的方法!我的想法是启动一个计数器,它在pressed()发出时开始,在发出released()时停止。但我目前还不知道如何等待已发布或类似的事件。通常我会connect()一个有插槽的信号,但在这种情况下两者都是插槽。也许你有一个更好的主意,也许这个很好。

2 个答案:

答案 0 :(得分:4)

pressed时。启动计时器。当released检查计时器运行了多长时间(并停止)。将经过的时间保存在类中的变量中。

这至少是一种方法。

答案 1 :(得分: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();
}

通常不赞成拥有&#34;业务逻辑&#34;在UI对象中,我们可以将功能分为TimerWidgetController。所有这些对象外部的代码都建立了必要的连接。

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

当然,你可以尖叫,控制器,即使没有真正耦合到其他代码,仍然在某种程度上依赖于其余代码的设计。值得庆幸的是,它并非必须如此:lambdas使简单的改编变得简单。

我们可以使用&#34;外国&#34;控制器,由我们的大型商业供应商提供:

// 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,重建项目,然后继续。

当你发布问题的测试用例时,你应该倒退:你在这个答案的最后开始某个地方,然后按照你的方式开始,最小化设置。它可以帮助您更好地理解您自己的代码,因为详细程度最小化。我希望,它告诉我们,第一个版本和最后一个版本都具有相同的功能。