关于计时器:如何暂停和恢复Qtimer(Qt 5)

How to pause and resume a Qtimer (Qt 5)

我需要有关Qtimer使用的帮助。

我使用Qt 5.0.2,这是我的问题:

我正在尝试开发一个Timer,并且界面很简单:

只有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/ ,但没有结果。

这是我拥有的源代码:(我只输入了需要的内容)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 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

我该如何解决?

谢谢!

编辑:感谢库巴·奥伯(Kuba Ober),但能否请您向我解释您发布的代码?

暂停如何工作?


以下是SSCCE,已在Qt 4.8和5.1下进行了测试。

Screenshot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//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"

我为启动,停止,暂停和恢复设置了Timer类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
QTime totalTime, sinceStart;

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()));
    connect(this, SIGNAL(timeChanged(QTime)), timeEdit, SLOT(setTime(QTime)));
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this , SLOT(updateTime()));
}


void MainWindow::updateTime() {
   emit timeChanged(totalTime.addMSecs(sinceStart.elpased()));
}

void MainWindow::resumeSimulation() {
   sinceStart.restart();
   timer->start();
}

void MainWindow::pauseSimulation() {
   timer->stop();
   totalTime = totalTime.addMSecs(sinceStart.restart());
   emit timeChanged(totalTime);
}