Как приостановить и возобновить Qtimer (Qt 5)

Мне нужна помощь в использовании Qtimer.

Я работаю с Qt 5.0.2 и вот моя проблема:

Я пытаюсь разработать таймер, и интерфейс прост:

Есть всего 2 кнопки: кнопка «Старт», чтобы запустить таймер, и кнопка «Пауза», и QtimeEdit для отображения времени.

На этом скриншоте показано, как это выглядит: http://img834.imageshack.us/img834/1046/5ks6.png

Проблема в том, что функция паузы не работает. Я прочитал всю документацию о Qtimer здесь: http://harmattan-dev.nokia.com/docs/library/html/qt4/qtimer.html и здесь: qt.developpez.com/doc/5.0-snapshot/qtimer/, но безрезультатно.

Это исходный код, который у меня есть: (я помещаю только то, что нужно)

// Creation of the Buttons and the time area
void MainWindow::createBottom()
{

    bottom = new QWidget();

    play = new QPushButton("Launch",this);
    pause = new QPushButton("Pause",this);
    play->setDisabled(false);
    pause->setDisabled(true);
    timeEdit = new QTimeEdit(this);
    timeEdit->setDisplayFormat("mm:ss");

    layout->addWidget(play);
    layout->addWidget(pause);
    layout->addWidget(timeEdit );
    bottom->setLayout(layout);

    connect(play, SIGNAL(clicked()), this, SLOT(startSimulation()));
    connect(pause, SIGNAL(clicked()), this, SLOT(pauseSimulation()));
}

// to resume the timer where is was stopped
void MainWindow::resumeSimulation()
{
    timer->blockSignals( false );
    pause->setText("Pause");
    pause->disconnect(SIGNAL(clicked()));
    connect(pause, SIGNAL(clicked()), this, SLOT(pauseSimulation()));
    paused = false;

    timer->start();
    int timeOfPause = time->restart();
    int timeTotal = timeOfPause + timeElapsed;
    time->addMSecs(-timeTotal);

}

// to Start the timer
void MainWindow::pauseSimulation()
{
    timer->blockSignals(true);
    pause->setText("Resume");
    timer->stop();
    play->setDisabled(false);
    //pause->setDisabled(true);
    pause->disconnect(SIGNAL(clicked()));

    connect(pause, SIGNAL(clicked()), this, SLOT(resumeSimulation())); 
    paused = true;
}

// to Start the timer from zero.
void MainWindow::startSimulation()
{

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this , SLOT(updateTime()));
    timer->start(500);
    play->setDisabled(true);

    pause->setDisabled(false);
}

void MainWindow::updateTime()
{
    if(time == NULL)
    {
       time = new QTime(0,0,0,0);
       time->start();
    }
    //timeEdit->setTime(QTime::fromS(time->elapsed()));
    //time = &(time->addMSecs(1000));
    if(hasRestart)
    {
        time->restart();
        time->addMSecs(-timeElapsed);
        hasRestart = false;
    }
    else
    {
        timeElapsed =+ time->elapsed();
    }
    int seconds = 0;
    int minutes = 0;
    int hours = 0;

    if(!paused)
    {
            seconds = (timeElapsed/1000)%60;
            minutes = (timeElapsed/60000)%60;
            hours =  (timeElapsed/3600000)%24;
            std::cout << "Test : " << hours << ":" << minutes << ":" << seconds << std::endl;
            timeEdit->setTime(QTime(0,minutes,seconds,0));
            timeEdit->update();
    }
}

Когда я нажимаю кнопку «Пуск», таймер запускается хорошо, но когда я нажимаю «Пауза», он только приостанавливает его в графическом интерфейсе, но когда я возобновляю, он показывает текущее время, как если бы он не останавливался.

Например :

Я начал. Я делаю паузу в 00:05. Он блокирует видимо таймер. Жду 10 секунд. Я возобновляю таймер, он показывает 00:15 вместо 00:06

Как я мог это исправить?

Спасибо !

РЕДАКТИРОВАТЬ: Спасибо, Куба Обер, но не могли бы вы объяснить мне код, который вы разместили, пожалуйста?

Как работает пауза?


person user2717381    schedule 26.08.2013    source источник
comment
Нет, вы не положили только то, что нужно. Вы вкладываете только то, что считаете необходимым.   -  person Greenflow    schedule 26.08.2013
comment
Почему вы создаете новый объект QTimer каждый раз, когда запускаете симуляцию? Откуда timeElapsed получает свое значение?   -  person thuga    schedule 26.08.2013
comment
в вашем коде много проблем, но самая главная проблема в слоте updateTime(), который вы не показали.   -  person Marek R    schedule 26.08.2013
comment
А time->addMSecs(-timeTotal); ничего не делает. QTime::addMSecs Returns a QTime object containing a time ms milliseconds later than the time of this object (or earlier if ms is negative). Значит должно быть time = time->addMsecs(-timeTotal);   -  person thuga    schedule 26.08.2013


Ответы (3)


Ниже приведен SSCCE, протестированный как для Qt 4.8, так и для 5.1.

Скриншот примера

//main.cpp
#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QElapsedTimer>
#include <QTime>

class Window : public QWidget {
    Q_OBJECT
    int m_timerId;
    qint64 m_accumulator;
    QLabel *m_label;
    QElapsedTimer m_timer;
    Q_SLOT void on_restart_clicked() {
        m_accumulator = 0;
        m_timer.restart();
        if (m_timerId == -1) m_timerId = startTimer(50);
    }
    Q_SLOT void on_pause_clicked() {
        if (m_timer.isValid()) {
            m_accumulator += m_timer.elapsed();
            m_timer.invalidate();
        } else {
            m_timer.restart();
            m_timerId = startTimer(50);
        }
    }
    void timerEvent(QTimerEvent * ev) {
        if (ev->timerId() != m_timerId) {
            QWidget::timerEvent(ev);
            return;
        }
        QTime t(0,0);
        t = t.addMSecs(m_accumulator);
        if (m_timer.isValid()) {
            t = t.addMSecs(m_timer.elapsed());
        } else {
            killTimer(m_timerId);
            m_timerId = -1;
        }
        m_label->setText(t.toString("h:m:ss.zzz"));
    }
public:
    explicit Window(QWidget *parent = 0, Qt::WindowFlags f = 0) : QWidget(parent, f), m_timerId(-1)  {
        QVBoxLayout * l = new QVBoxLayout(this);
        QPushButton * restart = new QPushButton("Start");
        QPushButton * pause = new QPushButton("Pause/Resume");
        restart->setObjectName("restart");
        pause->setObjectName("pause");
        m_label = new QLabel("--");
        l->addWidget(restart);
        l->addWidget(pause);
        l->addWidget(m_label);
        QMetaObject::connectSlotsByName(this);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}

#include "main.moc"
person Kuba hasn't forgotten Monica    schedule 26.08.2013
comment
SSCCE должен быть наименее запоминающейся аббревиатурой всех времен. Хотя идея мне нравится. - person Jesse Aldridge; 01.10.2014

Я сделал класс Timer для запуска, остановки, паузы и возобновления.

class MyTimer
    {
    public:
        MyTimer();
        QTime m_qtime;
        int m_accumulator;
        void start();
        int stop();
        void pause();
        void resume();
    };
MyTimer::MyTimer()
    :m_accumulator(0), m_qtime(QTime())
{
}

void MyTimer::start()
{
    m_qtime.start();
    m_accumulator = 0;
}

int MyTimer::stop()
{
    if(!m_qtime.isNull())
    {
        int l_elapsedTime = m_qtime.elapsed();
        m_accumulator += l_elapsedTime;
    }
    m_qtime = QTime();
    return m_accumulator;
}


void MyTimer::pause()
{
    if(!m_qtime.isNull())
    {
        int l_elapsedTime = m_qtime.elapsed();
        m_accumulator += l_elapsedTime;
    }
}


void MyTimer::resume()
{
    if(!m_qtime.isNull())
    {
        m_qtime.restart();
    }
}
person Vinoj John Hosan    schedule 16.02.2017

person    schedule
comment
Marek R: я получил: ошибка qt c3861 'timeChanged' идентификатор не найден - person user2717381; 26.08.2013
comment
@user2717381 user2717381 Вы объявили этот сигнал в своем MainWindow.h? - person thuga; 26.08.2013
comment
Неа. Как это должно выглядеть? пустое время изменено (Qtime & t); ? - person user2717381; 26.08.2013
comment
@ user2717381 Это может быть void timeChanged(QTime time); или void timeChanged(const QTime &time);. - person thuga; 26.08.2013
comment
Хорошо, у меня нет ошибки компиляции, но у меня все еще та же проблема, которую я описал. Кстати, я добавил метод updateTime() в свой первый пост. - person user2717381; 26.08.2013