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();
相关推荐
roman_日积跬步-终至千里16 小时前
【强化学习基础(2)】被动强化学习:学习价值函数
学习
逢考必过@k16 小时前
6级550学习ing
学习
陈天伟教授17 小时前
基于学习的人工智能(7)机器学习基本框架
人工智能·学习
Z***G47918 小时前
网络爬虫学习:借助DeepSeek完善爬虫软件,实现模拟鼠标右键点击,将链接另存为本地文件
爬虫·学习·计算机外设
我命由我1234520 小时前
微信开发者工具 - 模拟器分离窗口与关闭分离窗口
前端·javascript·学习·微信小程序·前端框架·html·js
DKPT20 小时前
ZGC和G1收集器相比哪个更好?
java·jvm·笔记·学习·spring
Main. 2421 小时前
从0到1学习Qt -- 常见控件之显示类控件
qt·学习
e***193521 小时前
爬虫学习 01 Web Scraper的使用
前端·爬虫·学习
二川bro1 天前
多模态AI开发:Python实现跨模态学习
人工智能·python·学习
石像鬼₧魂石1 天前
Netcat,网络瑞士军刀(新手学习备用)
学习