Qt 程序中QApplication对象的重写

前段时间在项目中遇到功能,实现一个自动锁屏的功能,说白了,就是通过某种手段实时监控鼠标和键盘的操作情况,在设定的时间内无操作时,调用自定义锁屏功能,我们选择使用重写QApplication类来实现。
Qt程序在运行到退出的过程中是一直在进行着事件循环,因此我们可以在事件循环中去截取信号,然后实现一些特殊的功能。
由于QApplication类在整个运行过程中都存在,我们也可以通过重写该类实现一些全局的功能。下面主要看下该类的实现,
首先我们定义一个类GlobalApplication继承自QApplication:

#include <QObject>
#include <QTimer>
#include <QApplication>
class GlobalApplication : public QApplication
{
	Q_OBJECT
public:
	GlobalApplication(int &argc, char **argv);	//构造函数的参数与main()函数保持一致,**必须使用引用传值**
	~GlobalApplication();
	bool notify(QObject* obj, QEvent* event);
private slots:
	void slot_timeOut();
private:
	QTimer*			m_pTimer; //定时器
	QThread*		m_pThread; //定时器线程
    Mainwindow*		m_pWidget;  //执行锁屏功能的类
};

值得注意的一点:
QApplication,QCoreApplication和QGuiApplication的构造函数中,argc必须使用引用传值的方式,否则会崩溃

下面看下他的构造:

GlobalApplication::GlobalApplication(int &argc, char **argv) : QApplication(argc, argv)
 , m_pTimer(Q_NULLPTR)
 , m_pThread(Q_NULLPTR)
 , m_pWidget(Q_NULLPTR) //该指针可以通过调用方法来设置
{
	int nTimer = 5; //设置自动锁屏的超时时间,该时间可由配置文件导入
	m_pThread = new QThread();
	m_pTimer = new QTimer(this);
	m_pTimer->moveToThread(m_pThread);  //开启一个线程用来进行计时器的运行
	connect(m_pThread, SIGNAL(started()), m_pTimer, SLOT(start()));
	connect(m_pTimer, &QTimer::timeout, this, &GlobalApplication::slot_timeOut);
	m_pTimer->setInterval(nTimer * 60000);
	m_pThread->start();
}
/**实现超时槽函数,可在次函数中实现一些定时操作的任务**/
void GlobalApplication::slot_timeOut()
{
	if (!m_pWidget || m_pWidget->isLockScreen())
	{
		return;
	}
	m_pWidget->lockScreen();    //定时任务
}

其中最主要的是实现notify函数, 该函数在程序运行过程中被不断的调用(事件循环)

bool GlobalApplication::notify(QObject* obj, QEvent* e)
{
	if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::KeyPress)
	{
		m_pThread->quit();  
	}
	else if (e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::KeyRelease)
	{
		m_pThread->start();
	}
	if (e->type() == QEvent::KeyPress)
	{
		/***********
         *
         *  do something...
         *
        ***********/
	}
    return QApplication::notify(obj, e);
}
void GlobalApplication::setWindowInstance(Mainwindow *wnd)
{
	m_pWidget = wnd;	/**可以将外部的类传进来**/
}

最重要的一点,我们需要将main.cpp中main()函数里面的QApplication替换为我们前面自定义的类。如下:

int main(int argc, char *argv[])
{
    GlobalApplication a(argc, argv);

    Style w;
    w.show();
    return a.exec();
}

以上,在我们需要一些全局操作来说,功能能够满足,重写该类的用途还有很多,比如在两个没有任何关系的类里面通过该类进行信号的传递。比如:
在设置信号的类里面通过调用:

auto application = dynamic_cast<GlobalApplication*>(QApplication::instance());

来获取全局QApplication的实例,然后通过调用GlobalApplication的方法设置信号,在获取信号的类里面同样能够获取到QApplication的实例,再调用方法来获取信号。

其实我们都知道,Qt的程序里面有个 qApp的全局对象,他的定义如下:

#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))

那么猜想一下,我们能不能按照这种方式对我们自定义的 GlobalApplication 类也实现相同的对象呢?

#include <QObject>
#include <QTimer>
#include <QApplication>

class GlobalApplication;

#if defined(app )
#undef app 
#endif
#define app static_cast<GlobalApplication*>(QCoreApplication::instance())
//#define app static_cast<GlobalApplication*>(QApplication::instance())

class GlobalApplication : public QApplication
{
	Q_OBJECT
	...
};

也就是说上面的这种实现方式可不可行,这样定义之后,我们就不会在后面的需要使用到GlobalApplication对象的时候使用dynamic_cast<GlobalApplication*>(QApplication::instance()); 这种方式去获取了。

通过验证,这种方式是可行的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值