效果说明:①通过对话框显示系统当前时间 ②秒针所指的刻度会变化为红色,当指到十二时,所有时刻都会变红
首先,设置视窗与窗口大小,配置坐标系;
然后,绘制表盘与指针;
最后,编写指针的旋转及变色方法;
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
#include
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
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);
}
通过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)
};
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();
}
}
旋转的方法在绘制表盘的时候已经叙述清楚,这里不再重复
坐标系在旋转,而用来绘制指针的点坐标的集合并没有改变,逻辑坐标系改变,而坐标和窗口显示方向不变,根据相对运动,效果便呈现为指针的转动。
这里用的颜色来自于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();
}
方法与时针基本相同,不再详细叙述
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();
}
方法与时针基本相同,不再详细叙述
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();
}
在主函数中,我主要对绘图工具的默认样式以及计时器进行了配置
每隔1s,将会重新加载页面,那么所有绘图事件便要重新调用一遍。currentTIme() 所读取到的时间就会发生改变,时针、分针、秒针的绘制方法也会随之改变,从而实现时钟的运行效果。
#include "dialog.h"
#include "ui_dialog.h"
#include
#include
#include
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;
}