#include "mainwindow.h" #include "ui_mainwindow.h" #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_clock.start(); m_refreshTimer.setInterval(100); connect(&m_refreshTimer, &QTimer::timeout, this, &MainWindow::refreshDisplay); for (QSpinBox *spin : {ui->hoursSpin, ui->minutesSpin, ui->secondsSpin}) connect(spin, static_cast(&QSpinBox::valueChanged), this, &MainWindow::durationChanged); connect(ui->startButton, &QPushButton::clicked, this, [this] { m_countdown.start(m_clock.elapsed()); refreshDisplay(); }); connect(ui->pauseButton, &QPushButton::clicked, this, [this] { const auto previousState = m_countdown.state(); m_countdown.pause(m_clock.elapsed()); if (previousState == Countdown::State::Running && m_countdown.state() == Countdown::State::Finished && ui->soundCheck->isChecked()) QApplication::beep(); refreshDisplay(); }); connect(ui->resetButton, &QPushButton::clicked, this, [this] { m_countdown.reset(); refreshDisplay(); }); connect(ui->fullscreenButton, &QPushButton::clicked, this, [this] { if (isFullScreen()) showNormal(); else showFullScreen(); ui->fullscreenButton->setText(isFullScreen() ? tr("退出全屏") : tr("全屏显示")); }); auto *escape = new QShortcut(QKeySequence(Qt::Key_Escape), this); connect(escape, &QShortcut::activated, this, [this] { if (isFullScreen()) { showNormal(); ui->fullscreenButton->setText(tr("全屏显示")); } }); durationChanged(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::durationChanged() { const qint64 seconds = ui->hoursSpin->value() * 3600 + ui->minutesSpin->value() * 60 + ui->secondsSpin->value(); m_countdown.setDuration(seconds * 1000); refreshDisplay(); } void MainWindow::refreshDisplay() { const qint64 now = m_clock.elapsed(); const auto previousState = m_countdown.state(); m_countdown.update(now); const auto state = m_countdown.state(); const bool running = state == Countdown::State::Running; const bool paused = state == Countdown::State::Paused; if (running && !m_refreshTimer.isActive()) m_refreshTimer.start(); if (!running) m_refreshTimer.stop(); const qint64 remaining = m_countdown.remaining(now); // 向上取整:还剩 1 毫秒时显示 1 秒,真正到时才显示零。 const qint64 seconds = (remaining + 999) / 1000; ui->timeLabel->setText(QStringLiteral("%1:%2:%3") .arg(seconds / 3600, 2, 10, QLatin1Char('0')) .arg((seconds / 60) % 60, 2, 10, QLatin1Char('0')) .arg(seconds % 60, 2, 10, QLatin1Char('0'))); ui->progressBar->setValue(m_countdown.duration() == 0 ? 0 : static_cast(remaining * 1000 / m_countdown.duration())); ui->durationGroup->setEnabled(!running && !paused); ui->startButton->setEnabled(!running && m_countdown.duration() > 0); ui->pauseButton->setEnabled(running); ui->startButton->setText(paused ? tr("继续") : state == Countdown::State::Finished ? tr("重新开始") : tr("开始")); if (running) ui->statusLabel->setText(tr("正在计时")); else if (paused) ui->statusLabel->setText(tr("已暂停 · 点击“继续”接着计时")); else if (state == Countdown::State::Finished) ui->statusLabel->setText(tr("时间到!本轮计时已结束。")); else ui->statusLabel->setText(m_countdown.duration() > 0 ? tr("准备就绪 · 点击“开始”") : tr("请先设置大于 0 的时长。")); if (previousState == Countdown::State::Running && state == Countdown::State::Finished && ui->soundCheck->isChecked()) QApplication::beep(); }