QTimer类为我们提供了一个即可重复触发又可单次触发的定时器。它是一个高层次的应用程序接口。要使用它,只需创建一个QTimer类对象,将它的timeout()信号连接到适当的函数上,然后调用其start()函数开启定时器即可,此后,QTimer对象就会周期性的发出timeout()信号。
例如,一个1s执行一次的定时器,可以如下设置:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
这样,update()就会每隔1秒被调用一次。
当然,我们也可以让一个QTimer对象在启动后只触发一次,只需调用该类的setSingleShot(true)即可。其实,更简单的做法是使用该类的静态方法QTimer::singleShot(),以某个时间间隔来启动一个单次触发的定时器。例如:
QTimer::singleShot(2000, this, SLOT(updateCaption()));
上面这句代码执行结束,2s后会调用一次updateCaption(),并且只调用一次。
要注意的是在多线程程序中,我们可以在任何开启了事件循环的线程中启动定时器。而要在一个非GUI线程中开启事件循环,则需要调用QThread::exec()。而Qt会使用定时器的线程依附性来决定由哪个线程发出timeout()信号。鉴于此,必须在定时器对象所在的线程中开启和结束定时器,不能跨线程操作。
比较特殊的一点是,在构建QTimer 对象时,可以传入0作为时间间隔。这样的定时器会在窗口系统的事件队列中的事件都被处理完之后触发。这可以用来在GUI程序中处理一些后台任务,比如垃圾收集。
下面我们使用QTimer类,来周期性的改变窗口的背景图片。
新建一个GUI工程Timer,完成后,在工程上点击右键,添加新文件,选中Qt Resource File,将我们需要的图片作为资源加入到工程中。如下图:
点击 Choose,在为资源文件起一个名字即可。如下图:
点击 下一步,在点击完成即可。
完成后,会在工程目录中生成一个资源目录,如下图:
然后,在res.qrc上,右键->open in editor,打开资源编辑器。如下图:
点击 添加->添加前缀,添加一个简单的前缀即可,一般在 前缀 那一栏填入"/"即可。
在点击 添加->添加文件 ,将准备好的图片添加进来即可。添加完成后,如下图:
这样,我们就可以在代码中使用这些图片了。至于Qt的资源系统,大家有时间的话可以自行参考Qt帮助文档学习,此处就不展开讲了。
先来看头文件widget.h的代码:
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void paintEvent(QPaintEvent*);
private slots:
void timeout();
private:
Ui::Widget *ui;
QTimer* timer;
QImage images[12];
int index;
};
#endif // WIDGET_H
在头文件中,我们先重写了paintEvent()事件,该事件就是用来重绘窗口的,我们以会就是在这个函数中向界面上绘制我们的图片。然后我们还定义了一个timeout()槽函数,该函数用来响应定时器QTimer的timeout()信号(注意,不要和上面的timeout()搞混,一个是槽,一个是信号,此处只是名字而已,大家在可以将上面的槽函数timeout()改为其他的名字)。最后,我们定义了一个定时器对象,一个QImage图片数组,用来存储我们的12张星座图片,还定义了一个index下标,用来在每次界面重绘的事件中标识不同的图片。
下面来看一个窗口的构造函数:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
images[0] = QImage(":/images/1.jpg");
images[1] = QImage(":/images/2.jpg");
images[2] = QImage(":/images/3.jpg");
images[3] = QImage(":/images/4.jpg");
images[4] = QImage(":/images/5.jpg");
images[5] = QImage(":/images/6.jpg");
images[6] = QImage(":/images/7.jpg");
images[7] = QImage(":/images/8.jpg");
images[8] = QImage(":/images/9.jpg");
images[9] = QImage(":/images/10.jpg");
images[10] = QImage(":/images/11.jpg");
images[11] = QImage(":/images/12.jpg");
index = 0;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
timer->start(1000);
}
在构造函数中,我们先使用我们添加的资源图片初始化了我们的图片数组,注意Qt中使用资源加载图片的方式,已":"开始,后面是图片在资源文件中的具体路径。然后,将index初始化为0,即重第一张图片开始显示。最后,实例化定时器对象,连接其timeout()信号到我们定义的timeout()槽函数上,再以1s为间隔启动定时器。
timeout()槽函数实现如下:
void Widget::timeout()
{
update();
}
在定时器到期函数中,我们只是简单的调用了QWidget类的update()函数,该函数会触发窗口的重绘,即会触发paintEvent()函数的调用。
paintEvent()实现如下:
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawImage(rect(), images[index++ % 12]);
}
在paintEvent()函数中,我们每次将下标index % 12 表示的图片绘制到窗口上,然后将index自增。从而实现12张图片的轮播。
启动程序,运行结果如下,12张星座图片以1s为间隔,不断在窗口中轮播: