qt学习:linux监听键盘alt+b和鼠标移动事件

目录

步骤

keylistener.cpp

keylistener.h

使用方法


linux中键盘和鼠标事件都是在/dev/input中,名字为eventX或者mouse

步骤

  • 创建一个继承线程类的KeyListener类
  • 重写run函数
  • 定义一个键盘的信号和一个鼠标的信号
  • 创建对象关联信号使用

keylistener.cpp

复制代码
#include "keylistener.h"
#include <QDebug>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include <QPoint>

KeyListener::KeyListener(const QString &devicePath, QObject *parent)
    : QThread(parent), devicePath(devicePath) {}

KeyListener::~KeyListener() {
    running = true;
    // 等待线程安全退出
    wait();
}

void KeyListener::run() {
    // 初始化鼠标在左上角坐标
    QPoint point(0,0);
    // 打开键盘事件文件
    int keyboardFd = open(devicePath.toStdString().c_str(), O_RDONLY);
    if (keyboardFd < 0) {
        qWarning() << "无法打开设备文件:" << devicePath;
        return;
    }

    // 打开鼠标事件文件
    mouseDevice = "/dev/input/event0";
    int mouseFd = open(mouseDevice.toStdString().c_str(), O_RDONLY);
    if (mouseFd < 0) {
        qWarning() << "无法打开鼠标设备文件:" << mouseDevice;
        close(keyboardFd);
        return;
    }
    // input事件结构体
    struct input_event ev;
    // 记录 Alt 键状态
    bool altPressed = false;
    // 一直循环
    while (running) {
        // 定义文件描述符集合
        fd_set readFds;
        // 将文件描述符集合清零
        FD_ZERO(&readFds);
        // 将键盘描述符写入集合
        FD_SET(keyboardFd, &readFds);
        // 将鼠标描述符写入集合
        FD_SET(mouseFd, &readFds);
        // 获取较大值
        int maxFd = std::max(keyboardFd, mouseFd);

        // 使用 select() 监听多个文件描述符  需要检查的文件描述符范围是 [0, maxFd-1]
        int ret = select(maxFd + 1, &readFds, nullptr, nullptr, nullptr);
        if (ret < 0) {
            qWarning() << "select() 失败";
            break;
        }

        // 处理键盘事件  检查 keyboardFd(键盘文件描述符)是否就绪。如果就绪,说明键盘有输入数据可读取
        if (FD_ISSET(keyboardFd, &readFds)) {
            // 从键盘文件描述符中读取输入事件结构体数据
            ssize_t bytes = read(keyboardFd, &ev, sizeof(struct input_event));
            // 检查读取的数据是否完整,并确认事件类型为键盘按键事件(EV_KEY 表示按键事件)
            if (bytes == sizeof(struct input_event) && ev.type == EV_KEY) {
                // 检查是否是左Alt键(KEY_LEFTALT)或右Alt键(KEY_RIGHTALT)的按键事件
                if (ev.code == KEY_LEFTALT || ev.code == KEY_RIGHTALT) {
                    // 更新 Alt 键状态
                    altPressed = ev.value == 1;
                }
                if (ev.code == KEY_B && ev.value == 1 && altPressed) {
                    // 触发 Alt+B 信号
                    emit altBPressed();
                }
            }
        }

        // 处理鼠标事件   检查 mouseFd 鼠标文件描述符是否就绪
        if (FD_ISSET(mouseFd, &readFds)) {
            // 从鼠标文件描述符中读取输入事件结构体数据
            ssize_t bytes = read(mouseFd, &ev, sizeof(struct input_event));
            // 检查读取的数据是否完整,并根据事件类型处理鼠标事件
            if (bytes == sizeof(struct input_event) && ev.type == EV_REL) {
                qDebug() << "鼠标移动事件,X、Y轴:" << ev.code << ", 移动量:" << ev.value;
                 // 根据事件代码(ev.code)确定是 X 轴还是 Y 轴的移动
                if (ev.code == REL_X) {
                    // 累加 X 轴的移动值
                    point.setX(point.x() + ev.value);
                } else if (ev.code == REL_Y) {
                    // 累加 Y 轴的移动值
                    point.setY(point.y() + ev.value);
                }
                // 发送鼠标移动事件传递鼠标坐标
                emit mouseMove(point);
            }
            // 鼠标按键事件
            else if (bytes == sizeof(struct input_event) && ev.type == EV_KEY)
            {
                qDebug() << "鼠标按键事件,按键:" << ev.code << ", 状态:" << ev.value;
            }
        }
    }

    close(keyboardFd);
    close(mouseFd);
}

keylistener.h

复制代码
#ifndef KEYLISTENER_H
#define KEYLISTENER_H

#include <QObject>
#include <QThread>
#include <QString>
#include <linux/input.h>
#include <fcntl.h>
#include <unistd.h>
#include <QDebug>
#include <QPoint>

class KeyListener : public QThread {
    Q_OBJECT

public:
    explicit KeyListener(const QString &devicePath, QObject *parent = nullptr);
    ~KeyListener();

    void run() override;  // 重写 QThread 的 run 方法

signals:
    void altBPressed();  // 触发 Alt+B 的信号
    void mouseMove(const QPoint &globalPos); // 发送鼠标坐标信号

private:
    QString devicePath;// 键盘事件驱动路径
    QString mouseDevice;// 鼠标事件驱动路径
    bool running = true;
};

#endif // KEYLISTENER_H

使用方法

复制代码
    // 需要启用鼠标跟踪
    this.setMouseTracking(true);    
    // 创建线程监听键盘事件
    const QString devicePath = "/dev/input/event1";
    m_listener = new KeyListener(devicePath, this);
    // 键盘监听触发截图
    connect(m_listener, &KeyListener::altBPressed,this, 键盘处理时间,Qt::QueuedConnection);
    connect(m_listener, &KeyListener::mouseMove,this, 鼠标处理事件,Qt::QueuedConnection);
    // 开始监听
    m_listener->start();
相关推荐
rannn_11130 分钟前
【MySQL学习|黑马笔记|Day7】触发器和锁(全局锁、表级锁、行级锁、)
笔记·后端·学习·mysql
喜欢吃燃面1 小时前
C++算法竞赛:位运算
开发语言·c++·学习·算法
传奇开心果编程1 小时前
【传奇开心果系列】Flet框架实现的家庭记账本示例自定义模板
python·学习·ui·前端框架·自动化
_Kayo_7 小时前
node.js 学习笔记3 HTTP
笔记·学习
CCCC131016310 小时前
嵌入式学习(day 28)线程
jvm·学习
星星火柴93611 小时前
关于“双指针法“的总结
数据结构·c++·笔记·学习·算法
小狗爱吃黄桃罐头11 小时前
正点原子【第四期】Linux之驱动开发篇学习笔记-1.1 Linux驱动开发与裸机开发的区别
linux·驱动开发·学习
艾莉丝努力练剑12 小时前
【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)
c语言·开发语言·数据结构·c++·学习·算法
武昌库里写JAVA13 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
杜子不疼.14 小时前
《Python学习之字典(一):基础操作与核心用法》
开发语言·python·学习