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();
相关推荐
上海广测检测科技有限公司5 小时前
蓝牙鼠标键盘台湾NCC认证详解:射频器材型式核准制度与技术标准解读
计算机外设
咸鱼翻身小阿橙7 小时前
现在这个四通道出现的问题
学习
云贝教育-郑老师8 小时前
OceanBase 是如何搞定海量数据分片(Sharding)的?
学习·oceanbase·dba
编程圈子8 小时前
电机驱动开发学习23. 保护体系与故障状态机
驱动开发·学习
别动我齐刘海10 小时前
Day6 unitree_G1人形机器人GMR—— MotionInput
c语言·c++·人工智能·学习·机器学习·机器人·github
神秘的MT10 小时前
C# WinForm Socket 服务器 + 串口转发
服务器·网络·学习·c#
zzzll111111 小时前
0基础入门大模型:一份清晰的学习路线图
人工智能·学习·chatgpt
正经人_x12 小时前
学习日记48:DenseCLIP
学习
DevangLic12 小时前
monkeycode-使用说明
学习·ai
red_redemption13 小时前
自由学习记录(211)
学习