QT开发(十六)——QT绘图实例-钟表

QT开发(十六)——QT绘图实例-钟表

一、钟表实现原理

钟表的实现需要设置定时器,定时器每隔一秒发送timeout()信号到QWidget::update()槽函数,update()槽函数将会重绘一次窗口,重写重绘事件函数paintEvent(QPaintEvent *event),根据获取的当前系统时间的时钟、分钟、秒钟重绘钟表的时针、分针、秒针。

QTimer *timer = new QTimer(this);

timer->start(1000);//一秒钟

connect(timer,SIGNAL(timeout()),this,SLOT(update()));

setWindowTitle("The Clock");

二、钟表的界面绘制

钟表由时针、分针、秒针、刻度盘组成,绘制时针、分针、秒针、刻度盘刻度线需要翻转坐标系,因此在绘制前需要先保存当前的坐标系状态,对坐标系进行翻转需要的角度后绘制图形,绘制完成后需要恢复坐标系的状态。

1、时针绘制

确定组成时针的四个点,使用drawConvexPolygon函数绘制出四边形时针。

const QPoint Clock::hourHand[4] = {

QPoint(3, 5),

QPoint(0, 13),

QPoint(-3, 5),

QPoint(0, -40)

};

QPainter painter(this);

painter.setBrush(Qt::black);

painter.setPen(Qt::black);

painter.drawConvexPolygon(hourHand,4);//绘制时针

2、分针绘制

确定组成分针的四个点,使用drawConvexPolygon函数绘制出四边形分针。

const QPoint Clock::minuteHand[4] = {

QPoint(3, 5),

QPoint(0, 16),

QPoint(-3, 5),

QPoint(0, -70)

};

QPainter painter(this);

painter.setBrush(Qt::black);

painter.setPen(Qt::black);

painter.drawConvexPolygon(minuteHand,4);//绘制分针

3、秒针绘制

确定组成秒针的四个点,使用drawConvexPolygon函数绘制出四边形秒针。

const QPoint Clock::secondHand[4] = {

QPoint(3, 5),

QPoint(0, 18),

QPoint(-3, 5),

QPoint(0, -90)

};

QPainter painter(this);

painter.setBrush(Qt::black);

painter.setPen(Qt::black);

painter.drawConvexPolygon(secondHand,4);//绘制秒针

4、钟表刻度盘绘制

钟表刻度盘分为时钟刻度和分钟刻度,分钟刻度每隔一分钟一根刻度线,因此坐标轴系统顺时针旋转6°时为一个分钟刻度,但是由于时钟刻度线与分钟刻度线重合,每隔30°的分钟刻度线同时也为时钟刻度线。

void Clock::drawClockDial(QPainter *painter)
{
     for (int i = 1; i <=60; ++i)
    {
        painter->save();
        painter->rotate(6*i);//坐标轴旋转6度
        if (i % 5 == 0)
        {
            painter->setPen(hourHandPen);
            painter->drawLine(0, -98, 0, -82);
            painter->drawText(-20, -82, 40, 40,
              Qt::AlignHCenter | Qt::AlignTop,QString::number(i/5));
        }
        else
        {
            painter->setPen(minuteHandPen);
            painter->drawLine(0, -98, 0, -88);
        }
        painter->restore();//绘制图形后复位坐标系
    }
}

三、钟表的业务逻辑

钟表正确计时必须依赖于获取系统时间,根据获取的系统时间计算出的时钟、分钟、秒钟的数重绘时针、分针、秒针。

1、时针的重绘

时针指向的位置需要计算时针偏转的角度,每两个时钟刻度线相隔30°,因此根据获取的系统时间计算出的小时数与30相乘即可等到时针需要顺时针偏转的角度。

30.0*(time.hour()+time.minute()/60.0)

时针重绘代码:

QTime time = QTime::currentTime();

painter->setBrush(Qt::black);

painter->setPen(Qt::black);

painter->save();

painter->rotate(30.0*(time.hour()+time.minute()/60.0));

painter->drawConvexPolygon(hourHand,4);//绘制时针

painter->restore();//绘制图形后复位坐标系

2、分针的重绘

分针指向的位置需要计算分针偏转的角度,每两个分钟刻度线相隔6°,因此根据获取的系统时间计算出的分钟数与6相乘即可等到分针需要顺时针偏转的角度。

6.0*(time.minute()+time.second()/60.0)

分针重绘代码:

QTime time = QTime::currentTime();

painter->setBrush(Qt::blue);

painter->setPen(Qt::blue);

painter->save();

painter->rotate(6.0*(time.minute()+time.second()/60.0));

painter->drawConvexPolygon(minuteHand,4);//绘制分针

painter->restore();//绘制图形后复位坐标系

3、秒针的重绘

秒针指向的位置需要计算秒针偏转的角度,秒针指向的是分钟刻度线,每两个分钟刻度线相隔6°,因此根据获取的系统时间计算出的秒钟数与6相乘即可等到秒针需要顺时针偏转的角度。

6.0*time.second()

分针重绘代码:

QTime time = QTime::currentTime();

painter->setBrush(Qt::red);

painter->setPen(Qt::red);

painter->save();//保存坐标系,防止坐标系跑偏了

painter->rotate(6.0*time.second());//注意是6.0,不是6

painter->drawConvexPolygon(secondHand,4);//绘制秒针

painter->restore();//绘制图形后复位坐标系

四、代码实现

Clock.h文件:

#ifndef CLOCK_H
#define CLOCK_H
#include <QtGui/QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QTime>
#include <QTimer>
#include <QPen>
#include <QFont>
class Clock : public QWidget
{
    Q_OBJECT
    
public:
    Clock(QWidget *parent = 0);
    ~Clock();
private:
    static const QPoint hourHand[4];
    static const QPoint minuteHand[4];
    static const QPoint secondHand[4];
    QPen hourHandPen;
    QPen minuteHandPen;
    QFont font;
protected:
    void paintEvent(QPaintEvent *event);
    void drawHourHand(QPainter *painter);
    void drawMinuteHand(QPainter *painter);
    void drawsecondHand(QPainter *painter);
    void drawClockDial(QPainter *painter);
};
#endif // CLOCK_H

Clock.cpp文件:

#include "Clock.h"
const QPoint Clock::hourHand[4] = {
    QPoint(3, 5),
    QPoint(0, 13),
    QPoint(-3, 5),
    QPoint(0, -40)
};
const QPoint Clock::minuteHand[4] = {
    QPoint(3, 5),
    QPoint(0, 16),
    QPoint(-3, 5),
    QPoint(0, -70)
};
const QPoint Clock::secondHand[4] = {
    QPoint(3, 5),
    QPoint(0, 18),
    QPoint(-3, 5),
    QPoint(0, -90)
};
Clock::Clock(QWidget *parent)
    : QWidget(parent)
{
    hourHandPen = QPen(palette().foreground(), 2.0);//设置小时刻度线为粗黑
    minuteHandPen = QPen(palette().foreground(), 1.0);//设置分钟刻度线为灰
    font.setPointSize(10);//字体大小设置为10
    setFont(font);
    QTimer *timer = new QTimer(this);
    timer->start(1000);//一秒钟
    connect(timer,SIGNAL(timeout()),this,SLOT(update()));
    setWindowTitle("The Clock");
    resize(360, 360);
}
Clock::~Clock()
{
}
void Clock::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    int side = qMin(width(), height());
    painter.setViewport((width() - side) / 2, (height() - side) / 2,
                        side, side);
    painter.setWindow(0, 0, 200, 200);
    painter.translate(100,100);//重新设定坐标原点
    drawClockDial(&painter);
    drawHourHand(&painter);
    drawMinuteHand(&painter);
    drawsecondHand(&painter);
    painter.setBrush(Qt::black);
    painter.drawEllipse(QPoint(0,0),3,3);
}
void Clock::drawHourHand(QPainter *painter)
{
    QTime time = QTime::currentTime();
    painter->setBrush(Qt::black);
    painter->setPen(Qt::black);
    painter->save();
    painter->rotate(30.0*(time.hour()+time.minute()/60.0));
    painter->drawConvexPolygon(hourHand,4);//绘制时针
    painter->restore();//绘制图形后复位坐标系
}
void Clock::drawMinuteHand(QPainter *painter)
{
    QTime time = QTime::currentTime();
    painter->setBrush(Qt::blue);
    painter->setPen(Qt::blue);
    painter->save();
    painter->rotate(6.0*(time.minute()+time.second()/60.0));
    painter->drawConvexPolygon(minuteHand,4);//绘制分针
    painter->restore();//绘制图形后复位坐标系
}
void Clock::drawsecondHand(QPainter *painter)
{
    QTime time = QTime::currentTime();
    painter->setBrush(Qt::red);
    painter->setPen(Qt::red);
    painter->save();//保存坐标系,防止坐标系跑偏了
    painter->rotate(6.0*time.second());//注意是6.0,不是6
    painter->drawConvexPolygon(secondHand,4);//绘制秒针
    painter->restore();//绘制图形后复位坐标系
}
void Clock::drawClockDial(QPainter *painter)
{
    //绘制钟表刻度盘和数字
    for (int i = 1; i <=60; ++i)
    {
        painter->save();
        painter->rotate(6*i);//坐标轴旋转6度
        if (i % 5 == 0)
        {
            painter->setPen(hourHandPen);
            painter->drawLine(0, -98, 0, -82);
            painter->drawText(-20, -82, 40, 40,
                              Qt::AlignHCenter | Qt::AlignTop,
                              QString::number(i/5));
        }
        else
        {
            painter->setPen(minuteHandPen);
            painter->drawLine(0, -98, 0, -88);
        }
        painter->restore();//绘制图形后复位坐标系
    }
}

Main.cpp文件:

#include <QtGui/QApplication>
#include "Clock.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Clock w;
    w.show();
    return a.exec();
}
时间: 2024-08-01 22:43:16

QT开发(十六)——QT绘图实例-钟表的相关文章

QT开发(六十五)——QT样式表编程实例

QT开发(六十五)--QT样式表编程实例 一.QComboBox组合框样式定制 1.基本定义 QComboBox  {     border: 1px solid gray;     border-radius: 3px;     padding: 1px 2px 1px 2px;  # 针对于组合框中的文本内容     min-width: 9em;   # 组合框的最小宽度 } QComboBox::drop-down {     subcontrol-origin: padding;   

QT开发(六十二)———QT5解析Json文件

QT开发(六十二)---QT5解析Json文件 一.QT5 Json简介 QT4中使用第三方库QJson解析JSON文件. QT5新增加了处理JSON的类,类均以QJson开头,包含在QtCore模块中.QT5新增加六个相关类: QJsonArray 封装 JSON 数组 QJsonDocument 读写 JSON 文档 QJsonObject 封装 JSON 对象 QJsonObject::iterator 用于遍历QJsonObject的STL风格的非const遍历器 QJsonParseE

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

QT开发(六)——QT容器组件

QT开发(六)--QT容器组件 QT中有九种容器组件,分别是组合框QGroupBox.滚动区QScrollArea.工具箱QToolBox.选项卡QTabWidget.控件栈QWidgetStack.框架QFrame.组件QWidget.MDI窗口显示区QMdiArea.停靠窗口QDockWidget. 一.QGroupBox分组框 1.QGroupBox组件简介 QGroupBox为构建分组框提供了支持.分组框通常带有一个边框和一个标题栏,作为容器部件来使用,在其中可以布置各种窗口部件.分组框

QT开发(六十一)———Json简介

QT开发(六十一)---Json简介 一.JSON简介 1.JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集. JSON采用完全独立于语言的文本格式,使用了类C语言家族的习惯(包括C.C++.C#.Java.JavaScript.Perl.Python等). JSON使用JavaScript语法来描述数据对象,但

BizTalk开发系列(三十六) Orchestration单实例执行

BizTalk 是高效的消息处理引擎,采用多线程并发的方式来处理消息.也就是说当有消息被接收的时候就会产生一个新的消息处理实例.但有时目标系统可能并没有并发处理 的能力, 这时就需要在BizTalk中采用单实例的方式来处理消息.在BizTalk的管道中直接可以启用按序送达的方式来实现, 但是在Orchestration中并没有提供类似的选项.该如何做到呢? 其实在BizTalk中可以根据设置消息的Correlation Set也就是相关属性来实现这样的效果.也就是第一条消息进来之后创建一个Orc

Develop -- Training(十六) -- 显示绘图和OpenGL ES

Android framework提供了许多标准的工具,来创建有吸引力的.功能丰富的用户图形界面.但是,如果你想要更多的控制权,比如在应用程序的屏幕上绘图,或者冒险进入三维图形,你需要使用不同的工具.通过Android framework提供的OpenGL ES的API提供了一套显示高端的工具,动画图像超出你的想象,许多Android设备的图像处理单元得到了加速(GPUs). 这节课主要开发一个OpenGL应用程序.包括设置.画对象.移动对象元素.响应触摸输入事件. 这节课的示例代码使用的是Op

Java微信公众平台开发(十六)--微信网页授权(OAuth2.0授权)获取用户基本信息

转自:http://www.cuiyongzhi.com/post/78.html 好长时间没有写文章了,主要是最近的工作和生活上的事情比较多而且繁琐,其实到现在我依然还是感觉有些迷茫,最后还是决定静下心来坚持一开始的选择,继续我们的微信系列文章的后续更新,也希望在自己有时间的时候能把更多的内容呈现给大家,前面一系列的文章讲述了很多微信开发相关的基础知识点 [微信系列文章],那么从这一篇开始将讲述微信较深一层次或者说在产品应用中时刻会用到的一些技术点,那么下面就让我们进入正题吧,这一篇我要讲述的

python运维开发(十六)----Dom&amp;&amp;jQuery

内容目录: Dom 查找 操作 事件 jQuery 查找 筛选 操作 事件 扩展 Dom 文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把网页和脚本以及其他的编程语言联系了起来.DOM属于浏览器,而不是JavaScript语言规范里的规定的核心内容. 查找元素 直接查找 document.getElementById 根据ID获取一个标签 doc