• Qt之模拟时钟


    简述

    Qt自带的示例中有一个是关于时钟,演示了如何用QPainter的转换和缩放特性来绘制自定义部件。

    其中主要包含了时针、分针的绘制,并不包含秒针。下面,我们在原示例的基础上进行扩展。

    实现方式

    由于时钟是妙级更新的,所以我们需要定时刷新,时钟则使用之前讲过的QPainter 2D图形来进行绘制。

    1. 使用QTimer定时刷新,设置超时时间为1000毫秒(1秒)。
    2. 绘制时钟,通过paintEvent()实现,包括:时针、分针、秒针、及面板、表盘等。

    示例

    效果

    这里写图片描述

    源码

    首先,我们构造一个定时器QTimer,连接其超时信号timeout()到槽函数update(),当调用update()时,系统会自动通知当前界面进行重绘(paintEvent())。

    MainWindow::MainWindow(QWidget *parent)
        : CustomWindow(parent)
    {
        ...
    
        // 构造定时器,设置超时为1秒
        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(update()));
        timer->start(1000);
        ...
    }

    重写paintEvent(),用于绘制时钟。

    void MainWindow::paintEvent(QPaintEvent *event)
    {
        Q_UNUSED(event);
    
        // 时针、分针、秒针位置 - 多边形
        static const QPoint hourHand[3] = {
            QPoint(7, 8),
            QPoint(-7, 8),
            QPoint(0, -30)
        };
        static const QPoint minuteHand[3] = {
            QPoint(7, 8),
            QPoint(-7, 8),
            QPoint(0, -65)
        };
    
        static const QPoint secondHand[3] = {
            QPoint(7, 8),
            QPoint(-7, 8),
            QPoint(0, -80)
        };
    
        // 时针、分针、秒针颜色
        QColor hourColor(127, 0, 120);
        QColor minuteColor(0, 127, 127, 120);
        QColor secondColor(0, 160, 230, 120);
    
        int side = qMin(width(), height());
        QTime time = QTime::currentTime();
    
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        // 平移坐标系原点至中心点
        painter.translate(width() / 2, height() / 2);
        // 缩放
        painter.scale(side / 200.0, side / 200.0);
    
        // 绘制时针
        painter.setPen(Qt::NoPen);
        painter.setBrush(hourColor);
    
        painter.save();
        // 每圈360° = 12h 即:旋转角度 = 小时数 * 30°
        painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
        painter.drawConvexPolygon(hourHand, 3);
        painter.restore();
    
        painter.setPen(hourColor);
    
        // 绘制小时线 (360度 / 12 = 30度)
        for (int i = 0; i < 12; ++i) {
            painter.drawLine(88, 0, 96, 0);
            painter.rotate(30.0);
        }
    
        // 绘制分针
        painter.setPen(Qt::NoPen);
        painter.setBrush(minuteColor);
    
        painter.save();
        // 每圈360° = 60m 即:旋转角度 = 分钟数 * 6°
        painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
        painter.drawConvexPolygon(minuteHand, 3);
        painter.restore();
    
        painter.setPen(minuteColor);
    
        // 绘制分钟线 (360度 / 60 = 6度)
        for (int j = 0; j < 60; ++j) {
            if ((j % 5) != 0)
                painter.drawLine(92, 0, 96, 0);
            painter.rotate(6.0);
        }
    
        // 绘制秒针
        painter.setPen(Qt::NoPen);
        painter.setBrush(secondColor);
    
        painter.save();
        // 每圈360° = 60s 即:旋转角度 = 秒数 * 6°
        painter.rotate(6.0 * time.second());
        painter.drawConvexPolygon(secondHand, 3);
        painter.restore();
    }

    好了,注释写的很清楚了,就不多做讲解了,如果要做一个应用,可以自己实现一些设置指针、表盘样式外观的一些接口。

    更多参考

    • Analog Clock Example - 助手
  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/itrena/p/5938239.html
Copyright © 2020-2023  润新知