秒表

源码上传:https://github.com/data1213/-

1、UI设计:

2、代码:

Qtime、Qtimer类

需求:每隔1ms,更新显示,怎么通知计时周期到:

QTimer类帮助文档:

1       QTimer *timer = new QTimer(this);
2       connect(timer, SIGNAL(timeout()), this, SLOT(update()));
3       timer->start(1000);  //1s

怎么获取时间数据:QTime帮助文档:

1 QTime 定义一个对象,它可以记录时间,并且可以人为指定时间,还有addMSecs方法可以实现增加指定毫秒,从而达到计数。

 1 Example:
 2 
 3   QTime n(14, 0, 0);                // n == 14:00:00
 4   QTime t;
 5   t = n.addSecs(70);                // t == 14:01:10
 6   t = n.addSecs(-70);               // t == 13:58:50
 7   t = n.addSecs(10 * 60 * 60 + 5);  // t == 00:00:05
 8   t = n.addSecs(-15 * 60 * 60);     // t == 23:00:00
 9 
10 See also addMSecs(), secsTo(), and QDateTime::addSecs().

通过toString方法可以获取一个QString类型的时间字符串:

1 QString QTime::toString(const QString &format) const
2 
3 
4 Format ---> Result
5 hh:mm:ss.zzz              14:13:09.042
6 h:m:s ap                  2:13:9 pm
7 H:m:s a                   14:13:9 pm

怎么显示到QLCDNumber控件:QLCDNumber帮助文档:

1 [slot] void QLCDNumber::display(const QString &s)
2 Displays the number represented by the string s.

这里的display方法是一个槽函数,这就是说明,槽函数可以像普通函数一样被调用,而不一定非要绑定信号才能调用。

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include <QTime>
 6 #include <QTimer>
 7 
 8 namespace Ui {
 9 class MainWindow;
10 }
11 
12 class MainWindow : public QMainWindow
13 {
14     Q_OBJECT
15 
16 public:
17     explicit MainWindow(QWidget *parent = nullptr);
18     ~MainWindow();
19 
20 
21 private slots:
22     void update_my_timer();
23 
24     void on_btn_begin_clicked();
25 
26 private:
27     QTime count_time;       //计数,用于更新定时器
28     QTimer* p_timer;        //定时器
29     Ui::MainWindow *ui;
30 };
31 
32 #endif // MAINWINDOW_H
 1 #include "mainwindow.h"
 2 #include "ui_mainwindow.h"
 3 #include <QDebug>
 4 
 5 MainWindow::MainWindow(QWidget *parent) :
 6     QMainWindow(parent),
 7     ui(new Ui::MainWindow)
 8 {
 9     ui->setupUi(this);
10     this->p_timer = new QTimer();
11     connect(this->p_timer, SIGNAL(timeout()), this, SLOT(update_my_timer())); //绑定定时器和槽函数
12 
13 }
14 
15 MainWindow::~MainWindow()
16 {
17     delete ui;
18 }
19 
20 
21 //计时周期到响应的槽函数
22 void MainWindow::update_my_timer(){
23     //1、更新当前计数
24     this->count_time = this->count_time.addMSecs(1); //增加1ms
25     //2、控件显式更新
26     QString timev = this->count_time.toString("hh:mm:ss.zzz");
27     qDebug()<<timev;
28     this->ui->lcdNumber->display(timev);
29 
30 }
31 
32 //点击开始按钮之后触发计时器开始计时
33 void MainWindow::on_btn_begin_clicked()
34 {
35     this->p_timer->start(1);  //启动1ms周期的定时器开始计时
36     //0、清空计数
37     this->count_time.setHMS(0,0,0,0);
38 }

效果:

改进:这里在设置计数时,认为设定从00:00:00:00开始,并且1ms计时周期,较短,需要处理的函数调用较多,这样容易出现问题,比如:当前进程较多,count_timer的计数有可能没有计到数,这样显式出来的就是错误的。

改进的做法:利用系统时间之差,来作为计数,这样系统时间始终是正确的,显式的始终是正确的。

1 int QTime::msecsTo(const QTime &t) const    //返回两个QTime之间的ms差
2 [static] QTime QTime::currentTime()
 1 //计时周期到响应的槽函数
 2 void MainWindow::update_my_timer(){
 3     //记录当前时间
 4     QTime c_time = QTime::currentTime();
 5     int diff = this->count_time.msecsTo(c_time);
 6 
 7     QTime temp;
 8     temp.setHMS(0,0,0,0);
 9 
10     temp = temp.addMSecs(diff);
11     QString str = temp.toString("hh:mm:ss.zzz");
12     this->ui->lcdNumber->display(str);
13 
14 }
15 
16 //点击开始按钮之后触发计时器开始计时
17 void MainWindow::on_btn_begin_clicked()
18 {
19     this->p_timer->start(1);  //启动1ms周期的定时器开始计时
20     //0、记录当前时间
21     this->count_time = QTime::currentTime();
22 }

功能完善以及按钮逻辑设定:

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include <QTime>
 6 #include <QTimer>
 7 
 8 namespace Ui {
 9 class MainWindow;
10 }
11 
12 class MainWindow : public QMainWindow
13 {
14     Q_OBJECT
15 
16 public:
17     explicit MainWindow(QWidget *parent = nullptr);
18     ~MainWindow();
19 
20 
21 private slots:
22     void update_my_timer();
23 
24     void on_btn_begin_clicked();
25 
26     void on_btn_end_clicked();
27 
28     void on_btn_hold_clicked();
29 
30     void on_btn_flag_clicked();
31 
32 private:
33     QTime count_time;       //计数,用于更新定时器
34     QTimer* p_timer;        //定时器
35     QString show_time;        //用于打点记录
36     Ui::MainWindow *ui;
37 };
38 
39 #endif // MAINWINDOW_H
  1 #include "mainwindow.h"
  2 #include "ui_mainwindow.h"
  3 #include <QDebug>
  4 
  5 MainWindow::MainWindow(QWidget *parent) :
  6     QMainWindow(parent),
  7     ui(new Ui::MainWindow)
  8 {
  9     ui->setupUi(this);
 10     this->p_timer = new QTimer();
 11     connect(this->p_timer, SIGNAL(timeout()), this, SLOT(update_my_timer())); //绑定定时器和槽函数
 12 
 13     //一开始只设置开始按钮可用
 14     this->ui->btn_hold->setEnabled(false);
 15     this->ui->btn_flag->setEnabled(false);
 16     this->ui->btn_end->setEnabled(false);
 17 
 18 
 19 }
 20 
 21 MainWindow::~MainWindow()
 22 {
 23     delete ui;
 24 }
 25 
 26 
 27 //计时周期到响应的槽函数
 28 void MainWindow::update_my_timer(){
 29     //记录当前时间
 30     QTime c_time = QTime::currentTime();
 31     int diff = this->count_time.msecsTo(c_time);
 32 
 33     QTime temp;
 34     temp.setHMS(0,0,0,0);
 35 
 36     temp = temp.addMSecs(diff);
 37     QString str = temp.toString("hh:mm:ss.zzz");
 38     this->ui->lcdNumber->display(str);
 39 
 40     //为了实现打点记录,这里先获取下当前时间
 41     this->show_time = str;
 42 
 43 }
 44 
 45 //点击开始按钮之后触发计时器开始计时
 46 void MainWindow::on_btn_begin_clicked()
 47 {
 48     this->p_timer->start(1);  //启动1ms周期的定时器开始计时
 49     //0、记录当前时间
 50     this->count_time = QTime::currentTime();
 51 
 52     //避免再次点击,需要设置开始按钮不可用
 53     this->ui->btn_begin->setEnabled(false);
 54     //其他按钮可用
 55     this->ui->btn_hold->setEnabled(true);
 56     this->ui->btn_flag->setEnabled(true);
 57     this->ui->btn_end->setEnabled(true);
 58 }
 59 
 60 void MainWindow::on_btn_end_clicked()
 61 {
 62     if(this->ui->btn_end->text() == "停止"){
 63         this->p_timer->stop();
 64         this->ui->btn_end->setText("清零");
 65 
 66         this->ui->btn_hold->setEnabled(false);  //暂停不可用,开始也还是不能用
 67 
 68         //如果是点击暂停按钮之后(本身变成继续)点击停止,那么需要将暂停按钮重新设置为暂停
 69         this->ui->btn_hold->setText("暂停");
 70 
 71     }else {  //清零
 72         this->ui->lcdNumber->display("00:00:00:000");
 73         this->ui->textBrowser->clear();
 74         this->ui->btn_end->setText("停止");
 75 
 76         this->ui->btn_begin->setEnabled(true);  //开始按钮重新可用
 77         //this->ui->btn_hold->setEnabled(false);//暂停继续不可用
 78         this->ui->btn_flag->setEnabled(false);
 79         this->ui->btn_end->setEnabled(false);
 80     }
 81 }
 82 
 83 //暂停功能
 84 void MainWindow::on_btn_hold_clicked()
 85 {
 86     //old_time需要时静态的,记录点击暂停时的时间,保留到下次调用该函数——点击继续时调用
 87     static QTime old_time;
 88 
 89     if(this->ui->btn_hold->text() == "暂停"){
 90         old_time = QTime::currentTime();
 91         this->p_timer->stop();//暂停计数,当系统时间一直在走,而count_timer没有变化了
 92         this->ui->btn_hold->setText("继续");
 93     }else {
 94         QTime new_time = QTime::currentTime();
 95         int mdiff = old_time.msecsTo(new_time);
 96         //更新从上一次点击暂停到这次点击继续之间系统经过的时间,然后补偿给count_timer
 97         this->count_time = this->count_time.addMSecs(mdiff);
 98         //开启计时器
 99         this->p_timer->start(1);
100         this->ui->btn_hold->setText("暂停");
101     }
102 }
103 
104 //打点功能:
105 void MainWindow::on_btn_flag_clicked()
106 {
107     //获取当前计数,并显式在text brower控件中显式
108     //this->ui->lcdNumber->value();是一个double值,不是时间值
109     //this->ui->textBrowser->setText()方法会覆盖之前的文本内容
110     this->ui->textBrowser->append(this->show_time);
111 }

效果演示:

内在的趣味,表面的繁琐
原文地址:https://www.cnblogs.com/data1213/p/10808230.html