Qt Qml 实现键鼠长时间未操作锁屏
[toc]
关键字: Qt
、Qml
、QInputEvent
、QStandardItem
、eventFilter
摘要
今日需求:
项目中需要实时检测用户是否长时间为操作键盘和鼠标,如果超过预设时间未操作键盘和鼠标,则退出到锁屏界面,准确的说是启动屏保,当用户再次操作键盘或鼠标,则进去登录界面,及实现长时间未操作键盘鼠标就锁屏的功能。
实现思路
大致的实现想法如上图所示,就是启动一个QTimer
定时器,输入参数就是要规定的微操作时间,如果到时间,没有检测到键盘和鼠标的操作,就出发屏幕保护程序,接着持续监听,如果依旧为监测到键盘和鼠标操作,那就一直停留在屏保画面,如果有键盘或鼠标操作,那就进入到登录界面。如果检测到了键盘或鼠标操作,那就重置定时器,是定时器重新开始计时。
题外话:
这里因为我的时间是一个大致的时间范围,对时间的精确是要求其实没有多高,所以这里就直接使用了QTimer
,但是Qt的定时器,那精确性是出了名的,所以在对精确性要求比较高的场景下,可以使用其他方式实现定时器,而不用Qt自带的定时器。
键盘鼠标监控
百度到的方法
这个就有好多了, 可知直接重写键鼠事件,这个网上一大堆,示例代码如下:
class MyWidget : public QWidget {
public:
MyWidget(QWidget *parent = nullptr) : QWidget(parent) {
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
}
void handleMousePressEvent(QMouseEvent *event) override {
if (event->button() == Qt::LeftButton) {
// 处理鼠标左键按下事件
} else if (event->button() == Qt::RightButton) {
// 处理鼠标右键按下事件
} else if (event->button() == Qt::MiddleButton) {
// 处理鼠标中键按下事件
}
}
void handleMouseMoveEvent(QMouseEvent *event) override {
// 处理鼠标移动事件
}
void handleMouseReleaseEvent(QMouseEvent *event) override {
if (event->button() == Qt::LeftButton) {
// 处理鼠标左键释放事件
} else if (event->button() == Qt::RightButton) {
// 处理鼠标右键释放事件
} else if (event->button() == Qt::MiddleButton) {
// 处理鼠标中键释放事件
}
}
void handleKeyPressEvent(QKeyEvent *event) override {
if (event->key() == Qt::Key_Space) {
// 处理空格键按下事件
} else if (event->key() == Qt::Key_Enter) {
// 处理回车键按下事件
} else if (event->key() == Qt::Key_Backspace) {
// 处理退格键按下事件
}
}
private:
QPoint lastPos_{};
};
或者使用QInputEvent
和QStandardItem
,示例代码如下:
监测键盘事件:
void MainWindow::on_pushButton_clicked() {
QStandardItem *standardItem = new QStandardItem("0");
table->appendRow(standardItem);
connect(table->model(), &QTableModel::rowInserted, this, &MainWindow::updateNum);
}
void MainWindow::updateNum(const QModelIndex &index) {
if (index.row() == 0) {
QStandardItem *standardItem = static_cast<QStandardItem*>(index.internalPointer());
connect(standardItem, &QStandardItem::textChanged, this, [=]() {
qDebug() << "Key released: " << standardItem->text();
});
}
}
监测鼠标事件:
void MainWindow::on_pushButton_clicked() {
QStandardItem *standardItem = new QStandardItem("0");
table->appendRow(standardItem);
connect(table->model(), &QTableModel::rowInserted, this, &MainWindow::updateNum);
}
void MainWindow::updateNum(const QModelIndex &index) {
if (index.row() == 0) {
QStandardItem *standardItem = static_cast<QStandardItem*>(index.internalPointer());
connect(standardItem, &QStandardItem::textChanged, this, [=]() {
qDebug() << "Mouse released: " << standardItem->text();
});
}
}
我的自己方法
但是上面都不是我想要的,还是太复杂,我仅仅想要的就是检测键盘和鼠标操作,至于操作了什么,我并不关心。所以我开辟的新的方法。我这里使用了Qt 的事建过滤器eventFilter
1 首先安装全局事件过滤器
这我们需要给我们的QApplication
安装事建过滤器,代码如下
QApplication::instance()->installEventFilter(this);
2 在事件过滤器中监听键盘事件和鼠标事件
我们在事件过滤器中只需要比较事件是否为键盘事件或鼠标事件,代码如下:
/**
* 捕获键盘事件
**/
if(event->type() == QEvent::KeyPress || event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress)
{
m_lockScreenTimer->start(m_timerLong);
setLockScreen(false);
}
如上述代码,我监听了键盘按下事件、鼠标移动事件和鼠标按键按下事件。并且在监听到这三个事件中的其中一个的时候,就重置了定时器,并且锁屏标志位置位了false
3 实现定时器到时间触发锁屏信号
connect(m_lockScreenTimer,&QTimer::timeout,this,[=](){
setLockScreen(true);
m_lockScreenTimer->stop();
});
上述代码,如果到达预定时间,这触发对应的槽函数,这里我懒得写个函数了,直接使用了Lambda
表达式,主要就是把锁屏标志位置位true
,
4 使用Qt的属性系统
因为我参与的项目实际是QML项目,所以这里就能体现所Qt属性系统的香了,可以直接和QML 中的属性做无缝绑定。代码如下:
Q_PROPERTY(bool lockScreen READ lockScreen WRITE setLockScreen NOTIFY lockScreenChanged)
最后
因为是实际生产力业务代码,不方便暂时完整代码,仅分享一个思路供小伙伴们参考,如果哪里有不懂的地方或者疑问,可以直接留言问我就可以。