文章目录

  • 一、效果展示
  • 二、绘制原理详解
    • 1、绘制时钟盘
    • 2、绘制刻度线
    • 3、绘制刻度值
    • 4、绘制指针
  • 三、运行流程详解
  • 四、具体代码

一、效果展示

二、绘制原理详解

1、绘制时钟盘

首先我们需要确定绘制一个时钟表盘需要哪些参数,在此我把黑色圆环称为外部,白色圆称为内部。绘制时钟表盘我们需要确定时钟的中心(Center_pos)、外部表盘的半径(R_Edge)、内部表盘的半径(R_Inside)、圆心指针端点小圆半径(R_Pointer)、外部表盘的颜色(Color_Edge)、内部表盘的颜色(Color_Inside)。
之后对表盘进行拆分绘制
①、先以中心为圆心,外部表盘的半径为半径,外部表盘的颜色绘制一个圆;②、再以中心为圆心,内部表盘的半径为半径,内部表盘的颜色绘制一个圆;③、最后以中心为圆心,圆心指针端点小圆半径为半径,圆心指针端点小圆颜色绘制一个圆,这样我们的时钟盘就绘制好了。

2、绘制刻度线

刻度线是一条线段,所以我们需要确定线段的起点和终点。那么我们怎么才能求出刻度线的起点和终点呢?我们需要确定刻度线起点和终点的半径和角度就可以算出每条刻度线对应的起点和终点坐标。
确定角度:我们知道时钟有十二个大刻度(分别是1-12),每个大刻度之间又有五个小刻度,所以总共有12 * 5 = 60个刻度;一个圆有360°,所以每个刻度占360° / 60 = 6°。==坐标是以圆心所在横线右方向为x正半轴,圆心所在竖线上方向为y轴正半轴,0°参考点为x轴正半轴,顺时针旋转。==我们从圆心正上方(即12点)处开始绘制,那么我们的基础仰角就是90° * 3 = 270°,依次往下是276°、282°,以此类推。
确定半径:我们以刻度线靠近外部的端点称为起点,靠近内部的端点称为终点。从实物图可以看出,起点的半径即为内部圆的半径,且每条刻度线的起点对应的半径是相等的;终点的半径分为大刻度半径和小刻度半径,大刻度半径明显要小于小刻度半径,在此我们设置一个相对于内部圆半径的偏移值就可以了,但是一定要保证大刻度半径的偏移值要大于小刻度半径的偏移值。
知道了每条刻度线起点与终点对应的半径和每条刻度线对应的角度之后,我们就可以采用如下公式计算出起点和终点了:

int x = 圆心的横坐标 + 半径 * cos(角度 * PI /180);
int y = 圆心的纵坐标 + 半径 * sin(角度 * PI /180);

公式详解如下:

求出起点和终点之后我们就直接画线段就好了。

3、绘制刻度值

我们只需要在标注大刻度的值(即1-12),绘制字体我们需要确定绘制的坐标和内容。内容相对简单,至于绘制的坐标,可参考绘制刻度线是求坐标的办法,基本上一模一样,在此就不赘述了。唯一需要注意的是,我们绘制刻度值时,是绘制一个矩形,然后往里面填入想要绘制的文字。QRect是以左上角的坐标为参考,如果我们把计算得到的文字应填入的坐标直接传给QRect,那么就会出现刻度线和刻度值没对齐的现象,尤其是位数多的刻度值(例如12),所以我们在绘制刻度值时,应对求出的坐标做适当的偏移,这样就可以改善刻度值与刻度线不对齐的问题了。

4、绘制指针

时钟的指针分为时针、分针和秒针,绘制原理基本上一模一样,所以在此就以绘制时针为例说明一下。
时针我们将其看作是一个等腰三角形,底边在中心指针圆域中,顶点指向刻度,所以我们需要知道三个点的坐标才可以绘制出时针(三角形)。三个点的坐标求法参考求刻度线坐标的方法求解,无非就是半径大小发生了变化,大家可以仔细思考一下。求出坐标之后,就直接依据三个坐标绘制三角形,并填充为想要的颜色就行了。

三、运行流程详解

我们设置了一个定时1秒的定时器,让其调用update()函数,从而调用paintEvent()函数,所以绘制图形是始终在刷新的。我们可以通过QTime::currentTime.hourQTime::currentTime.minute
QTime::currentTime.second分别获取系统的时分秒,然后将其赋给H、M、S,这样由于时分秒始终在更新,而指针的绘制又依据了时分秒,这样就可以看到时钟指示的是当前的时间,并且指针一直在正常的运转。

四、具体代码

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QtMath>
#include <QTimer>#define PI 3.14class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();void paintEvent(QPaintEvent *);//重写绘制事件函数void Init_Parameter();//初始化参数函数void Set_Mask(QPainter *);//设置窗体透明void Draw_Clock(QPainter *);//绘制时钟void Draw_Broad(QPainter *);//绘制时钟盘void Draw_Dial(QPainter *);//绘制刻度盘void Draw_Text(QPainter *);//绘制刻度值void Draw_Pointer(QPainter *);//绘制指针private:QTimer *timer;//定时器QPoint Center_pos;//时钟圆心坐标int R_Edge;//外部圆半径int R_Inside;//内部圆半径int R_Center;//中心小圆半径int R_Pointer;//中心指针圆半径QColor Color_Edge = QColor(0,0,0,255);//外部圆颜色QColor Color_Inside = QColor(255,255,255,255);//内部圆颜色QColor Color_Center = QColor(0,0,0,255);//中心小圆颜色int Div_Max = 12;//大刻度值int Div_Min = 5;//小刻度值float BaseAngle = 270;//基础仰角int H;//时int M;//分int S ;//秒};#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include <QTime>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent)
{timer = new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(update()));//定时调用绘制事件函数timer->start(1000);//开启定时器,执行周期为1秒针}Widget::~Widget()
{}void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);//设置抗锯齿Draw_Clock(&painter);
}void Widget::Draw_Clock(QPainter *painter)
{Init_Parameter();Set_Mask(painter);Draw_Broad(painter);Draw_Dial(painter);Draw_Text(painter);Draw_Pointer(painter);
}void Widget::Init_Parameter()
{Center_pos = QPoint(this->width()/2,this->height()/2);//以窗体中心为圆心R_Edge = this->height()/2;//以窗体高度的一半为半径R_Inside = R_Edge-10;R_Center = 15;R_Pointer = 6;QTime Time = QTime::currentTime();//获取当前系统时间H=Time.hour();//分别设置时、分、秒M=Time.minute();S=Time.second();
}void Widget::Set_Mask(QPainter *painter)
{painter->save();//保存QBrush brush = QBrush(Qt::transparent);//设置画刷为透明painter->setBrush(brush);painter->fillRect(this->rect(),QColor(0,0,0,0));painter->restore();//恢复
}void Widget::Draw_Broad(QPainter *painter)
{painter->save();QBrush brush = QBrush(Color_Edge);//绘制外部圆painter->setBrush(brush);painter->drawEllipse(Center_pos,R_Edge,R_Edge);brush = QBrush(Color_Inside);//绘制内部圆painter->setBrush(brush);painter->drawEllipse(Center_pos,R_Inside,R_Inside);brush = QBrush(Color_Center);//绘制中心小圆painter->setBrush(brush);painter->drawEllipse(Center_pos,R_Center,R_Center);painter->restore();
}void Widget::Draw_Dial(QPainter *painter)
{painter->save();for(int Loop = 0; Loop <= Div_Max*Div_Min; Loop++){float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*Loop;//从基础仰角开始绘制的每条刻度线对应的角度int R = R_Inside-1;int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);if(Loop % Div_Min == 0)//判断是否为大刻度{QPen pen(Qt::black);pen.setWidth(4);painter->setPen(pen);R = R_Inside-20;}else  //判断是否为小刻度{QPen pen(Qt::black);pen.setWidth(2);painter->setPen(pen);R = R_Inside-15;}int x_end = Center_pos.x() + R * cos((Angle / 180) * PI);int y_end = Center_pos.y() + R * sin((Angle / 180) * PI);painter->drawLine(QPoint(x_start,y_start),QPoint(x_end,y_end));//绘制刻度线}painter->restore();
}void Widget::Draw_Text(QPainter *painter)
{painter->save();QPen qPen(Qt::black);qPen.setWidth(5);   //设置画笔的粗细painter->setPen(qPen);QFont qFont("楷体",28,QFont::Bold,false);painter->setFont(qFont);int Dial_Text = 12;for(int Loop = 0;Loop < Div_Max;Loop++){if(Dial_Text >12 )Dial_Text = 1;int R = R_Inside-60;float Angle = BaseAngle + (360 / Div_Max )*Loop;int x = Center_pos.x() + R * cos((Angle / 180) * PI);int y = Center_pos.y() + R * sin((Angle / 180) * PI);painter->drawText(QRect(x-20,y-20,80,80),QString::number(Dial_Text++));}painter->drawText(Center_pos.x()-60,Center_pos.y()+60,"劳力士");painter->restore();
}void Widget::Draw_Pointer(QPainter *painter)
{painter->save();QBrush qBrush = QBrush(QColor(Qt::black));painter->setBrush(qBrush);QPen qPen(Qt::black);qPen.setWidth(2);   //设置画笔的粗细painter->setPen(qPen);
//**********绘制秒针***********************************************************************************float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*S;float RightAngle = Angle + 90;//右侧角度float LeftAngle = Angle - 90;//左侧角度int R = R_Inside-1;int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);R = R_Pointer-1;int x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点int y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);int x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点int y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);QPointF qTriangle_S[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};painter->drawPolygon(qTriangle_S,3);
//**********绘制分针***********************************************************************************Angle = BaseAngle + (360 / (Div_Max * Div_Min))*M;RightAngle = Angle + 90;//右侧角度LeftAngle = Angle - 90;//左侧角度R = R_Inside-60;x_start = Center_pos.x() + R * cos((Angle / 180) * PI);y_start = Center_pos.y() + R * sin((Angle / 180) * PI);R = R_Pointer-1;x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);QPointF qTriangle_M[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};painter->drawPolygon(qTriangle_M,3);
//**********绘制时针***********************************************************************************Angle = BaseAngle + (360 / Div_Max)*H;RightAngle = Angle + 90;//右侧角度LeftAngle = Angle - 90;//左侧角度R = R_Inside-120;x_start = Center_pos.x() + R * cos((Angle / 180) * PI);y_start = Center_pos.y() + R * sin((Angle / 180) * PI);R = R_Pointer-1;x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);QPointF qTriangle_H[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};painter->drawPolygon(qTriangle_H,3);painter->restore();
}

QT自定义控件--时钟相关推荐

  1. linux qt 自定义控件,编写Qt Designer自定义控件(一)——如何创建并使用Qt自定义控件...

    要想在Qt Designer中使用自定义控件,必须要使Qt Designer能够知道我们的自定义控件的存在.有两种方法可以把新自定义控件的信息通知给Qt Designer:"升级(promo ...

  2. Qt自定义控件创建和使用

    Qt自定义控件创建和使用 Qt中很方便的是使用各种自定义控件来分模块实现各种子功能,用于实现代码的解耦: 之前在使用Qt 5.12创建自定义控件时,出现了各种问题,多次重装QtCreator和VS,屡 ...

  3. Qt自定义控件之仪表盘的完整实现

    概述 基于QT的仪表盘有很多种办法,比如使用QWT,ChartDirector 或H5混合的echart组件,或者基于QT的绘图功能绘制,或者基于美工提供的图片的基础上增加动态效果.然而搞明白QT自定 ...

  4. Qt自定义控件(IP输入框,windows下)

    1.建立自定义控件项目 组代表后来能从哪里找到 剩下的点"下一步"就行了 2.编辑代码 在生成项目的cpp中添加自己的内容(没有.ui界面了,设计tab是灰色的) 放一下我的代码 ...

  5. Qt自定义控件------SwitchButton

    简介   一般用来两种互斥状态的切换. 效果 下面放效果图 控件拆分 一.控件大体有两部分组成,一个是背景,一个是白色的滑块.原本背景是想用QWidget然后直接设置圆角的,然后发现效果很差.所以背景 ...

  6. 【Qt开发笔记】Qt自定义控件开发与使用,自定义控件实现容器与控件内布局

    1.开发环境 Qt版本:Qt 4.8.7 编译器:MinGw 系统:Windows 2.创建Qt4自定义控件 创建一个Qt自定义控件工程. 工程名为Custom. 控件类取名Custom. 然后完成创 ...

  7. Qt自定义控件之圆形按钮、圆形头像

    Qt自定义控件之圆形按钮.圆形头像 前言 代码实现 实验效果 前言 现在很多软件的头像或者按钮都是圆形了,看起来比较舒服.比如QQ登录头像,酷狗客户端的一些按钮都是圆形.Qt实现圆形头像,大致有几种思 ...

  8. Qt 自定义控件提升,头文件找不到的问题

    Qt 自定义控件提升,头文件找不到的问题 在附加包含目录添加: ./

  9. QT自定义控件(生成和使用)

    为什么80%的码农都做不了架构师?>>>    首先,打开Qt Creator,这不是废话莫, → 新建项目 (快捷键 [ Ctrl + N ])→ 其他项目 → Qt4 设计师自定 ...

最新文章

  1. java子类对象和成员变量的隐写方法重写
  2. LeetCode实战:不同路径
  3. OpenCV--SIFT算法检测特征点
  4. python3 gui tk代码_【基础】学习笔记30-python3 tkinter GUI编程-实操12
  5. mybatis直接执行sql语句后续之一
  6. java项目_值得学习和练手的Java企业级开源项目,强烈推荐!
  7. 2018蓝桥杯A组:分数(3种方法 循环累称 快速幂运算 移位运算)
  8. TinyMind 和机器之心收藏
  9. Atitit 可视化技术体系题 目录 1. 1. 可视化分类 1 1 1.1. 1.1. 层次可视化 金字塔等 层次降为3层归类可视化 1 1 1.2. 1.2. 高层可视化 鸟瞰可视化 1 1 1
  10. 机器学习 数据间的定义_定义数据科学,机器学习和人工智能
  11. 主成分分析与因子分析及SPSS实现
  12. GridinSoft CHM编辑器3.2.0多语言,轻松快速地翻译CHM电子书
  13. 华为力推自研AI芯片,还记得大明湖畔的寒武纪吗?
  14. win10 安装 frida 安装配置
  15. 《Python自然语言处理-雅兰·萨纳卡(Jalaj Thanaki)》学习笔记:05 特征工程和NLP算法
  16. C#、NPOI生成Word文档(模板)
  17. linux启动分区丢,Linux装机因为分区丢失引导解决办法
  18. 十分透彻:电容去耦原理
  19. 恶女阿楚在线观看,恶女阿楚剧情介绍
  20. Asp.Net 下载邮箱附件(随手笔记)

热门文章

  1. ACPI 待机/睡眠/休眠有啥区别?
  2. chipping rate码片速率
  3. React TypeScript 从零实现 Popup 组件发布到 npm
  4. 计算机网络系统的维护,简论事业单位计算机网络管理系统的维护
  5. 英语语法三大从句刷题总结
  6. 程序员的十层楼 11层(上帝)
  7. 秋天NET快速强签名工具V1.1
  8. PyTorch 加载预训练权重
  9. EDM邮件群发:群发邮件不进垃圾箱的独家秘笈
  10. [数值计算-17]:最小二乘法的求解2 - 二元二次线性方程组求解