2016-07-28 3 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(); 
} 

Это, как правило, с неодобрением, чтобы иметь «бизнес-логики» в объекты пользовательского интерфейса, таким образом, мы можем выделить функциональные возможности в том, что из 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" 

Конечно, вы можете кричать, что контроллер, даже если на самом деле не связан с другим кодом, все еще в некоторой степени зависит от конструкции остальной части кода. К счастью, это не обязательно так: lambdas упрощает простые адаптации.

Мы можем использовать «чужой» контроллер, предоставляемый нашей большой бизнес поставщика, также:

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

Все приведенные выше примеры являются compileable: поставить любой из них в main.cpp, перестроить проект, и идти.

Когда вы отправляете тестовые примеры для вопросов, вы должны вернуться назад: вы начинаете где-то ближе к концу этого ответа и прокладываете себе путь к началу, минимальной настройке. Это поможет вам лучше понять ваш собственный код, так как сглаженность свернута. Это говорит, я надеюсь, что и первая, и последняя версия имеют одинаковую функциональность.

+0

Один вопрос: если вы подключаете 2 сигнала друг к другу, какова его функциональность? Вот что я думаю: он работает как цепочка. Один сигнал излучает другой, и тот активирует подключенный слот. – tistCoder

+1

@tistCoder Вы можете подключить сигнал к чему угодно: методу или функтору. Подсоединение сигнала к сигналу означает, что когда первый сигнал испускается, второй сигнал вызывается (и, следовательно, испускается). Помните, что сигналы - это просто mc-генерируемые методы. –

+0

Спасибо за ваш ответ. Теперь я знаю намного больше, чем раньше – tistCoder

Смежные вопросы