之前接手的项目中有一个关于屏保的需求是,如果超过30s未进行操作,软件自动进入屏保状态。简单分析一下:所谓未进行操作即是指未接收到键盘或者鼠标事件,超过30s也就是需要用到定时器,屏保状态就是显示一张全屏大图。从QT的角度思考,我们需要创建一个屏保类并且将其做为应用程序的一个事件代理,如果其中有鼠标或者键盘事件,则重新刷新定时器,如果超过30s没有接收到相关事件则全屏显示屏保窗口。以下就着代码实例讲解一下。
构造一个屏保类CScreenSaver:
cscreensaver.h文件
#ifndef CSCREENSAVER #define CSCREENSAVER #ifndef QOBJECT_H #include <QObject> #endif class QTimer; class QLabel; class CScreenSaver : public QObject { Q_OBJECT public: CScreenSaver(QObject *parent = NULL); ~CScreenSaver(); protected slots: void slot_timeout(); protected: //初始化屏保参数 void init(); //事件接收处理函数,由installEventFilter调用方在接收到事件时调用 bool eventFilter(QObject *watched, QEvent *event); private: //定时器 QTimer *timer; //用于显示屏保图片的对象 QLabel *label; //初始屏保等待超时时间 static const unsigned WAIT_TIME = 30000; }; #endif
cscreensaver.cpp文件
#include <cscreensaver.h> #include <QFile> #include <QLabel> #include <QEvent> #include <QTimer> #include <QPixmap> #include <QSettings> CScreenSaver::CScreenSaver(QObject *parent) : QObject(parent), waitInterval(WAIT_TIME) { init(); } CScreenSaver::~CScreenSaver() { } void CScreenSaver::init() { unsigned waitInterval; QString urlPath; //读取屏保配置 QSettings settings(QApplication::applicationDirPath() + "/config.ini", QSettings::IniFormat); settings.beginGroup("SCREENSAVER"); if (settings.contains("Interval")) { bool ok; waitInterval = settings.value("Interval").toUInt(&ok); if (!ok) waitInterval = WAIT_TIME; } if (settings.contains("PicPath")) { urlPath = settings.value("PicPath").toString(); } settings.endGroup(); //设置并启动timer。如果超过30s,则一直显示屏保并不再触发直到再次刷新定时器 timer = new QTimer; timer->setSingleShot(true); connect(timer, SIGNAL(timeout()), this, SLOT(slot_timeout())); timer->start(waitInterval); //屏保窗口 QRect screenRect = QApplication::desktop()->screenGeometry(0); label = new QLabel(); label->setGeometry(screenRect); label->setWindowFlags(Qt::FramelessWindowHint); //拉伸背景图片 label->setScaledContents(true); QPixmap pmp; pmp.load(urlPath); label->setPixmap(pmp); label->hide(); } bool CScreenSaver::eventFilter(QObject *obj, QEvent *event) { //判断事件类型 if (event->type() == QEvent::KeyPress || event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress) { //有鼠标或键盘事件则重置timer timer->start(); label->hide(); } return QObject::eventFilter(obj, event); } void CScreenSaver::slot_timeout() { //显示屏保 label->activateWindow(); label->show(); }
main.cpp文件中
#include <QApplication> ... #include <cscreensaver.h> int main(int argc, char *argv[]) { QApplication app(argc, argv); ... CScreenSaver screenSaver; //全局接收并委托处理事件 app.installEventFilter(&screenSaver); ... return app.exec(); }