서론

 

간단하게 UI를 만들었다.

시 : 분 : 초.미리초 를 보여주게 하였고

버튼으로는 시작, 정지, 재시작, 랩을 배치하였다.

랩 버튼을 누르면 랩 타임을 listWidget에 기록하게 만들었다. 


코드

stopwatch.h

#ifndef STOPWATCH_H
#define STOPWATCH_H

#include <QDialog>
#include <QTimer>
#include <QTime>

namespace Ui {
class Stopwatch;
}

class Stopwatch : public QDialog
{
    Q_OBJECT

public:
    explicit Stopwatch(QWidget *parent = nullptr);
    ~Stopwatch();

private:
    Ui::Stopwatch *ui;
    QTimer *timer;
    int elapsedTime;
    QTime startTime;

private slots:
    void btn_start();
    void btn_stop();
    void btn_reset();
    void btn_lap();
    void update_display();
};

#endif // STOPWATCH_H

 

stopwatch.cpp

#include "stopwatch.h"
#include "ui_stopwatch.h"

Stopwatch::Stopwatch(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Stopwatch),
    timer(new QTimer(this))
{
    ui->setupUi(this);

    connect(ui->btn_start, &QPushButton::clicked, this, &Stopwatch::btn_start);
    connect(ui->btn_stop, &QPushButton::clicked, this, &Stopwatch::btn_stop);
    connect(ui->btn_reset, &QPushButton::clicked, this, &Stopwatch::btn_reset);
    connect(ui->btn_lap, &QPushButton::clicked, this, &Stopwatch::btn_lap);
    connect(timer, &QTimer::timeout, this, &Stopwatch::update_display);

    ui->watch->setText("00:00:00.000");
    ui->btn_stop->setEnabled(false);
}

Stopwatch::~Stopwatch()
{
    delete ui;
}

 

슬롯 함수 구현부

 

 

btn_start()

void Stopwatch::btn_start()
{
    ui->btn_start->setEnabled(false);
    ui->btn_stop->setEnabled(true);

    if (!timer->isActive()) {
        timer->start(10);
        startTime = QTime::currentTime();
    }
}
  • 타이머가 활성화 되어있지 않다면 10ms간격으로 시작
  • startTime에 시작 시간을 기록한다.

btn_stop()

void Stopwatch::btn_stop()
{
    ui->btn_start->setEnabled(true);
    ui->btn_stop->setEnabled(false);

    if (timer->isActive()) {
        timer->stop();
        elapsedTime += startTime.msecsTo(QTime::currentTime());
    }
}
  • 타이머가 활성회 되어있다면 stop
  • elapsedTime 변수에 현재 시각과 시작 시간의 차이를 추가한다.

btn_reset()

void Stopwatch::btn_reset()
{
    ui->btn_start->setEnabled(true);
    ui->btn_stop->setEnabled(false);
    
    timer->stop();
    elapsedTime = 0;
    ui->watch->setText("00:00:00.000");
    ui->listWidget->clear();
}
  • 타이머를 멈추고 모든 변수, 값들을 초기화

 

btn_lap()

void Stopwatch::btn_lap()
{
    ui->listWidget->addItem(ui->watch->text());
}
  • 현재 값을 listWidget에 기록

btn_display()

void Stopwatch::update_display()
{
    int totalElapsed = elapsedTime + startTime.msecsTo(QTime::currentTime());
    int milliseconds = totalElapsed % 1000;
    int seconds = (totalElapsed / 1000) % 60;
    int minutes = (totalElapsed / (1000 * 60)) % 60;
    int hours = (totalElapsed / (1000 * 60 * 60)) % 24;

    ui->watch->setText(QString("%1:%2:%3.%4")
                            .arg(hours, 2, 10, QChar('0'))
                            .arg(minutes, 2, 10, QChar('0'))
                            .arg(seconds, 2, 10, QChar('0'))
                            .arg(milliseconds, 3, 10, QChar('0')));
}

 

  • totalElapsed에 총 경과 시간을 계산

타이머 시나리오

  1. 스톱워치를 처음 시작할 때
    1. startTime은 현재 시간으로 설정, elapsedTime은 0으로 설정
  2. 1초 후 update_display가 호출될 때
    1. currentTime은 startTime에서 1초가 지난 시각
    2. startTime.msecsTo(currentTime)은 1000ms (1초)를 반환
    3. totalElapsed = elapsedTime + 1000ms = 0 + 1000 = 1000ms가 된다.
  3. 스톱워치를 2초 후 멈출 때
    1. currentTime은 startTime에서 2초가 지난 시각이다.
    2. startTime.msecsTo(currentTime)은 2000ms (2초)를 반환
    3. btn_stop() 함수가 호출되면 elapsedTime은 2000ms가 된다.
    4. timer가 멈추고 startTime은 그대로 유지된다.

결과