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();
相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习