analogClock画图解析
analogClock.h文件重载画图函数
paintEvent(QPaintEvent*)函数是QWidget类中的虚函数,用于ui的绘制。
由于定义的analogClock类的基类是QWidget类,因此,我们必须重载该函数。
首先,我们必须在analogClock.h文件中,添加重载函数,代码为:
protected:
void paintEvent(QPaintEvent *event) override;
Qt creator非常人性化,你只要输入protected:,然后输入void paintE,还没有等到你输入完,光标所在位置自动会显示出整个函数,选择paintEvent函数,回车即可。
analogClock.h的完整代码为:
#ifndef ANALOGCLOCK_H
#define ANALOGCLOCK_H
#include <QWidget>
class analogClock : public QWidget
{
Q_OBJECT
public:
analogClock(QWidget *parent = nullptr);
~analogClock();
protected:
void paintEvent(QPaintEvent *event) override;
};
#endif // ANALOGCLOCK_H
ananlogClock类的绘图所有语句,必须在paintEvent函数中给出。
当窗口有重绘事件发生时,Qt自动重绘窗口。大部分重绘事件为:
(1)repaint()函数或者update()函数被调用
(2)被隐藏的部件被重新显示
(3)初始化窗口
注意:
(1)Qt会通过合并多个重绘事件为一个事件,目的是用来加速绘制。例如,当update()函数被多次调用时,或者窗口系统发送了多个重绘事件,那么Qt会合并这些事件为一个事件。update()函数不会立即进行重绘。update()函数允许Qt优化速度和减少闪烁。
(2)repaint()函数调用时,会立即调用paintEvent()函数。
(3)当重绘事件发生时,要更新的区域,一般会被擦除,然后在部件的背景上进行重新绘制。
analogClock.cpp代码
在analogClock.h文档中,把光标移到paintEvent函数所在的行,按alt+Enter,Qt Creator自动在analogClock.cpp文件中添加paintEvent函数的定义。
构造函数添加代码
在analogClock类的构造函数中,我们添加如下代码:
analogClock::analogClock(QWidget *parent)
: QWidget(parent)
{
// 定义一个定时器,这里用指针
QTimer *timer = new QTimer(this);
// 利用connect将定时器的timeout()信号与对应槽函数连接
// 此处的槽函数为:QOverload<>of(&AnalogClock::update))
connect(timer,
&QTimer::timeout,
this,
QOverload<>::of(&analogClock::update));
// 1000 ms 也就是1s发送一个信号
timer->start(100);
// 程序标题
setWindowTitle(tr("师老师设计的时钟 2020a"));
// 初始化应用程序的大小400像素*400像素
resize(400,400);
}
用于这里用到了定时器,因此,必须在程序前面添加包含头文件,即
#include <QTimer>
代码解析:
(1)创建一个定时器类的对象
代码为:
QTimer *timer = new QTimer(this);
注意这里采用定时器类指针 QTimer *timer,也采用new操作符。注意这里虽然用new操作符新建QTimer类的指针,不用在析构函数中用delete操作符删除指针,Qt在程序退出的时候,自动销毁内存。这是Qt的特性。
(2)建立信号与槽函数
timer超时后,会发出信号timeout(),因此,必须在创建好的定时器对象后,给其建立信号与槽函数。
Qt传统方法为:
connect(timer,
SIGNAL(timeout()),
this,
SLOT(onTimeout()));
connect()函数有4个参数,第1个参数是timer对象指针;第3个参数是this指针;第2个参数是timer对象发出的信号,SIGNAL表示信号;第4个参数是槽函数,SLOT表示槽。
Qt 5.14.0中的方法有所不同,代码如下:
connect(timer,
&QTimer::timeout,
this,
QOverload<>::of(&analogClock::update));
首先,省略了SIGNAL和SLOT。
其次,用&QTimer::timeout替代原来的timeout(),语法上更为严谨,代码可读性更强。
最后,槽函数用&analogClock::update,前面还用了QOverload重载函数。该函数返回一个指向重载函数的指针。
qOverload()需要C++14的支持。在C++11风格的代码中,QOverload的用法为:
... QOverload<>::of(&Foo::overloadedFunction)
... QOverload<int, QString>::of(&Foo::overloadedFunction)
要通过函数指针的语法连接该信号,就可以借助qOverload类获取函数指针,这也是Qt官方文档推荐的连接方式。
(3)开启定时器
在需要的地方,开启定时器,采用现在代码:
timer->start(100);
start()函数参数是毫秒,这里是100ms发送一次timeout信号。
(4)修改程序标题
程序标题的修改非常简单,代码为:
setWindowTitle(tr("师老师设计的时钟 2020a"));
注意,这里采用setWindowTitle()函数,参数用tr()函数,里面是字符串,可以中英文混合。
(5)初始化analogClock窗口大小
程序一运行,我们希望初始化analogClock窗口的大小,代码为:
resize(400,400);
这里采用resize()函数,设置宽和高均为400个像素。
paintEvent函数代码
在paintEvent函数中添加如下代码:
void analogClock::paintEvent(QPaintEvent *event)
{
// 定义一个QPoint常量数组
static const QPoint hourHand[3] = {
QPoint(7,8),
QPoint(-7,8),
QPoint(0,-40)
};
static const QPoint minuteHand[3] = {
QPoint(5,8),
QPoint(-5,8),
QPoint(0,-70)
};
static const QPoint secondHand[3] = {
QPoint(3,8),
QPoint(-3,8),
QPoint(0,-88)
};
// 定义时针,分针,秒针的颜色
QColor hourColor(127,0,127);
QColor