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();
相关推荐
爱米的前端小笔记1 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
alikami1 小时前
【前端】前端学习
学习
一只小菜鸡..1 小时前
241118学习日志——[CSDIY] [ByteDance] 后端训练营 [06]
学习
Hacker_Oldv3 小时前
网络安全的学习路线
学习·安全·web安全
蒟蒻的贤3 小时前
vue学习11.21
javascript·vue.js·学习
高 朗3 小时前
【GO基础学习】基础语法(2)切片slice
开发语言·学习·golang·slice
码上有前3 小时前
解析后端框架学习:从单体应用到微服务架构的进阶之路
学习·微服务·架构
岳不谢4 小时前
VPN技术-VPN简介学习笔记
网络·笔记·学习·华为
海害嗨4 小时前
阿里巴巴官方「SpringCloudAlibaba全彩学习手册」限时开源!
学习·开源
小A1595 小时前
STM32完全学习——使用SysTick精确延时(阻塞式)
stm32·嵌入式硬件·学习