QT:绘制一个简易时钟(显示系统当前时间)
程序员文章站
2022-05-22 19:20:45
...
一、效果展示
效果说明:①通过对话框显示系统当前时间 ②秒针所指的刻度会变化为红色,当指到十二时,所有时刻都会变红
二、案例实现方法
1.案例实现的主要步骤概括
首先,设置视窗与窗口大小,配置坐标系;
然后,绘制表盘与指针;
最后,编写指针的旋转及变色方法;
2.头文件配置(头文件部分的注释我写的很清楚)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QTimer>
#include <QPen>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
static const QPoint hourHand[4];//用于保存时针图形
static const QPoint minuteHand[4];//用于保存分针图形
static const QPoint secondHand[3];//用于保存秒针图形
QPen HourHand_Pen;//时针画笔样式
QPen MinuteHand_Pen;//分针画笔样式
QFont font_01;//公用字体样式
protected:
void paintEvent(QPaintEvent *event);//绘图事件
void draw_HourHand(QPainter *painter);//时针绘制
void draw_MinuteHand(QPainter *painter);//分针绘制
void draw_SecondHand(QPainter *painter);//秒针绘制
void draw_ClockDial(QPainter *painter);//表盘绘制
};
#endif // DIALOG_H
3.绘图事件的配置
①坐标系配置
1.通过setViewport设定视窗,来确定逻辑坐标系;通过setWindow设定窗口,来确定物理坐标系(设备坐标系);这两个方法联合使用,可以达到确保时钟跟随窗口的大小而变化大小的效果。视窗的设定实际上就是将在逻辑坐标系上绘制的图形的指定部分映射到设备(例如:你的电脑屏幕上显示的对话框);
2.通过translate() 方法重新确定坐标原点,本案例中将实际坐标系的(100,100)设定为逻辑坐标系的(0,0)。
②将绘画操作绑定绘画事件
即:将接下来的绘制工作绑定到该绘画事件中
void Dialog::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);//避免运行程序时提示event未使用的警告
QPainter painter(this);
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);//重置逻辑坐标系原点
draw_ClockDial(&painter);//将绘制函数绑定该绘画事件
draw_HourHand(&painter);
draw_MinuteHand(&painter);
draw_SecondHand(&painter);
}
4.时钟指针的图形样式
通过QPoint类型保存多个点的坐标。在绘制时钟指针时,只需要分别将其作为参数传入 drawConvexPolygon() 方法中,便可以绘制对应的凸多边形,即本案例需要绘制的时钟指针。
const QPoint Dialog::hourHand[4]=
{
QPoint(3, 6),
QPoint(0, 10),
QPoint(-3, 6),
QPoint(0, -30)
};
const QPoint Dialog::minuteHand[4]=
{
QPoint(2, 6),
QPoint(0, 18),
QPoint(-2, 6),
QPoint(0, -65)
};
const QPoint Dialog::secondHand[3]=
{
QPoint(1, 20),
QPoint(-1, 20),
QPoint(0, -90)
};
5.表盘绘制
①系统当前时间的获取及应用
- 创建QTime类型,并将其赋值为QTime中的currentTime() 方法所返回的系统当前时间【这个时间同样是一个QTime类型】
- QTime类型下可以通过hour(),minute(),second() 方法分别获取该时间的时、分、秒数据,并该数据类型可以直接当做数来使用
②坐标系的旋转与保存
- 通过save() 可以保存初始坐标系,以便于在所有的旋转操作都进行完成之后通过restore() 方法来恢复初始坐标系,以便其他绘图事件的进行
- 通过rotate() 方法可以对逻辑坐标系进行旋转,因为绘图都是在逻辑坐标系上进行的,所以我们每隔1s便将逻辑坐标系旋转6度。经过60s后,逻辑坐标系便旋转了一周。旋转过程中,在我们需要的地方予以绘制便可
void Dialog::draw_ClockDial(QPainter *painter)
{
for(int i=1;i<=60;i++)
{
QTime time=QTime::currentTime();
painter->save();
painter->rotate(6*i);
if(i%5==0)
{
painter->setPen(HourHand_Pen);//选定画笔样式
painter->drawLine(0,-98,0,-82);//绘制整点刻度
QString x;//用于保存需要绘制的文本,即整点的罗马字符
switch(i)//通过switch语句,判断需要绘制的时刻字符
{
case 5:x="Ⅰ";break; case 10:x="Ⅱ";break; case 15:x="Ⅲ";break;
case 20:x="Ⅳ";break; case 25:x="Ⅴ";break; case 30:x="Ⅵ";break;
case 35:x="Ⅶ";break; case 40:x="Ⅷ";break; case 45:x="Ⅸ";break;
case 50:x="Ⅹ";break; case 55:x="Ⅺ";break; case 60:x="Ⅻ";break;
}
if(i!=time.second()&&time.second()!=0)//非整点时,罗马字符采用提前设置好的QPen
{
painter->setPen(HourHand_Pen);
painter->drawText(-20,-82,40,40,Qt::AlignHCenter|Qt::AlignTop,x);
}
else//整点时,罗马字符变色,重写Pen
{
painter->setPen(Qt::red);
painter->drawText(-20,-82,40,40,Qt::AlignHCenter|Qt::AlignTop,x);
}
}
else
{
if(i!=time.second())
{
painter->setPen(MinuteHand_Pen);
painter->drawLine(0,-98,0,-88);
}
else//整点时,刻度变色,重写Pen
{
painter->setPen(Qt::red);
painter->drawLine(0,-98,0,-88);
}
}
painter->restore();
}
}
6、时针绘制及旋转方法配置
旋转的方法在绘制表盘的时候已经叙述清楚,这里不再重复
①关于时钟指针转动的逻辑
坐标系在旋转,而用来绘制指针的点坐标的集合并没有改变,逻辑坐标系改变,而坐标和窗口显示方向不变,根据相对运动,效果便呈现为指针的转动。
②颜色的选取
这里用的颜色来自于QColor类中的fromRgb() 方法。参数便是RGB配色的三个参数,参数取值范围为 (0~255) 。RGB,即用R(red红)、G(green绿)、B(blue蓝)三种颜色的比例及深浅调和出来的颜色,具体的样式可以查一下RGB颜色表,对照着来选色。
void Dialog::draw_HourHand(QPainter *painter)
{
QTime time = QTime::currentTime();
painter->setBrush(QColor::fromRgb(139,134,130));
painter->setPen(QColor::fromRgb(139,134,130));
painter->save();
painter->rotate(30.0*(time.hour()+(double)time.minute()/60.0));
painter->drawConvexPolygon(hourHand,4);
painter->restore();
}
7、分针绘制及旋转方法配置
方法与时针基本相同,不再详细叙述
void Dialog::draw_MinuteHand(QPainter *painter)
{
QTime time = QTime::currentTime();
painter->setBrush(QColor::fromRgb(139,134,130));
painter->setPen(QColor::fromRgb(139,134,130));
painter->save();
painter->rotate(6.0*(time.minute()+(double)time.second()/60.0));
painter->drawConvexPolygon(minuteHand,4);
painter->restore();
}
8、秒针绘制及旋转方法配置
方法与时针基本相同,不再详细叙述
void Dialog::draw_SecondHand(QPainter *painter)
{
QTime time = QTime::currentTime();
painter->setBrush(QColor::fromRgb(0,160,230));
painter->setPen(QColor::fromRgb(0,160,230));
painter->save();
painter->rotate(6.0*(time.second()));
painter->drawConvexPolygon(secondHand,3);
painter->restore();
}
9、主函数配置
在主函数中,我主要对绘图工具的默认样式以及计时器进行了配置
时钟计时器的配置方法
- 利用QTimer类型启用计时器,时间间隔用startTimer() 方法设定为1000ms,即一秒。
- 运用信号和槽机制。在QTimer中有一个叫做timeout() 的方法,每经历指定时间间隔,便会发出信号,将该方法连接具有重新加载当前页面功能的update() 槽函数。
运行逻辑是:
每隔1s,将会重新加载页面,那么所有绘图事件便要重新调用一遍。currentTIme() 所读取到的时间就会发生改变,时针、分针、秒针的绘制方法也会随之改变,从而实现时钟的运行效果。
#include "dialog.h"
#include "ui_dialog.h"
#include <QPainter>
#include <QTime>
#include <QColor>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
HourHand_Pen = QPen(QColor::fromRgb(0,160,230));//设置时针默认画笔样式
MinuteHand_Pen=QPen(QColor::fromRgb(139,134,130));//设置分针默认画笔样式
font_01.setPointSize(10);//设置字体
setFont(font_01);//载入字体
QTimer* timer = new QTimer(this);//配置计时器
timer->start(1000);
connect(timer,SIGNAL(timeout()),this,SLOT(update()));//本案例的信号和槽机制
resize(300,300);//重新设定窗口大小
}
Dialog::~Dialog()
{
delete ui;
}