绘制时钟
一.效果展示
二.基本思路
首先是将表盘和时、分、秒针以及表框“绘制”出来,然后设置定时器,定时器每隔一秒发送timeout()信号到QWidget::update()槽函数,update()槽函数将会重绘一次窗口,重写重绘事件函数paintEvent(QPaintEvent *event),根据获取的当前系统时间的时钟、分钟、秒钟重绘钟表的时针、分针、秒针。
三.各部分绘制思路+实现代码
1.“绘制”时针、分针、秒针
定义三个数组,数组中的四个点连起来就是时针、分针、秒针。
const QPoint Widget::hourHand[4] = {
QPoint(3, 5),
QPoint(0, 13),
QPoint(-3, 5),
QPoint(0, -40)
};
const QPoint Widget::minuteHand[4] = {
QPoint(3, 5),
QPoint(0, 16),
QPoint(-3, 5),
QPoint(0, -70)
};
const QPoint Widget::secondHand[4] = {
QPoint(3, 5),
QPoint(0, 18),
QPoint(-3, 5),
QPoint(0, -90)
};
2.绘制表盘
在绘制刻度和数字的时候选择利用循坏同时进行。开始的save()函数是保存调整前的局部界面,最后的restore()函数是恢复到save()保存的那个界面,这两个函数在代码中的作用是保持坐标轴的一致性。之后每旋转6度就绘制一条刻度线,然后if (i % 5 == 0)即在整时的时候加上数字并将刻度线拉长加粗。
具体代码如下:
void Widget::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();//绘制图形后复位坐标系
}
}
3.设制背景——绘制表框
在事件函数中写入上次写到的填入背景图,这个背景图就是一个表框,然后让其铺满整个对话框,实现表框的绘制。
QPainter painter(this);
QPixmap map(":/res/1234.jpg");
QRect q(0,0,220,220);
QRect q2(0,0,width(),height());
painter.drawPixmap(q2,map,q);
绘制表框需要在源文件中添加类库
#include"QPixmap"
4.其他设置
hourHandPen = QPen(palette().foreground(), 2.0);//调色板,2.0,1.0为颜色代码,这里是调整刻度线的颜色
minuteHandPen = QPen(palette().foreground(), 1.0);
font.setPointSize(10);//字体大小设定为10
setFont(font);//设定默认字体
setWindowTitle("The Clock");//设置对话框名称
resize(220, 220);//重设对话框大小
四.各部分基本原理+实现代码(表盘+时、分、秒针+表框)
1.计时器
设定槽函数,每一秒钟调用一次事件函数
QTimer *timer = new QTimer(this);
timer->start(1000);//一秒钟
connect(timer,SIGNAL(timeout()),this,SLOT(update()));
2.重绘时针函数
根据获取的时间的小时数(分钟数也化为小时数)乘上30°将时针进行旋转,从而实现时针的实时走动。
void Widget::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();//绘制图形后复位坐标系
}
3.重绘分针函数
分针函数与时针函数基本相同,只是将实时的分钟数乘上6°旋转分钟(实际上是旋转坐标轴,然后在绘制的时候就看起来是分针在走动)。
void Widget::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();//绘制图形后复位坐标系
}
4.重绘秒针函数
实现原理与上面一致,秒针旋转的度数就直接是秒钟数乘上6°。
void Widget::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();//绘制图形后复位坐标系
}
5.事件函数
事件函数为Qt中的主要函数,是在运行时被自动调用的函数,然后计时器每一秒钟调用一次事件函数,同时事件函数调用重绘函数,实现钟表的重现绘制,从而实现时针、分针、秒针的走动。
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);
五.补充部分
在头文件中添加使用到的类库
#include <QPaintEvent>
#include <QPainter>
#include <QTime>
#include <QTimer>
#include <QPen>
#include <QFont>
声明Widget的成员函数及变量
(一般变量写在private中,函数protected中,有利于继承过程中封装性的维护)
private:
static const QPoint hourHand[4];
static const QPoint minuteHand[4];
static const QPoint secondHand[4];
QPen hourHandPen;
QPen minuteHandPen;
QFont font;
Ui::Widget *ui;
protected:
void paintEvent(QPaintEvent *event);
void drawHourHand(QPainter *painter);
void drawMinuteHand(QPainter *painter);
void drawsecondHand(QPainter *painter);
void drawClockDial(QPainter *painter);
感谢大家的浏览,如有错误,请不吝赐教!