欢迎访问cuzn小站

之前接手的项目中有一个关于屏保的需求是,如果超过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();
}