qt 鼠标 键盘 录制 及 回放 代码

时间: 2023-11-06 20:07:18 浏览: 53
以下是一个简单的 Qt 鼠标键盘录制及回放的示例代码: ```cpp #include <QApplication> #include <QWidget> #include <QMouseEvent> #include <QKeyEvent> #include <QTimer> #include <QFile> #include <QDataStream> class Recorder : public QObject { Q_OBJECT public: Recorder(QObject *parent = nullptr) : QObject(parent) { connect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); } public slots: void startRecording(QString filename) { if (m_file.isOpen()) { return; } m_file.setFileName(filename); if (!m_file.open(QIODevice::WriteOnly)) { return; } m_dataStream.setDevice(&m_file); m_dataStream.setVersion(QDataStream::Qt_5_15); m_recording = true; m_startTime = QDateTime::currentDateTime(); connect(qApp, &QApplication::focusChanged, this, &Recorder::onFocusChanged); connect(qApp, &QApplication::applicationStateChanged, this, &Recorder::onApplicationStateChanged); connect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); m_timer.start(20, this); } void stopRecording() { if (!m_recording) { return; } m_recording = false; m_timer.stop(); disconnect(qApp, &QApplication::focusChanged, this, &Recorder::onFocusChanged); disconnect(qApp, &QApplication::applicationStateChanged, this, &Recorder::onApplicationStateChanged); disconnect(qApp, &QApplication::aboutToQuit, this, &Recorder::stopRecording); m_file.close(); } void onMouseEvent(QMouseEvent *event) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::MouseButtonPress + event->button()); m_dataStream << event->pos(); } } void onKeyEvent(QKeyEvent *event) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::KeyPress + event->key()); m_dataStream << qint32(event->modifiers()); } } private slots: void onTimeout() { if (qApp->applicationState() == Qt::ApplicationActive) { QPoint pos = QCursor::pos(); m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::MouseMove); m_dataStream << pos; } } void onFocusChanged(QWidget *oldWidget, QWidget *newWidget) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::FocusOut); m_dataStream << oldWidget; m_dataStream << qint32(QEvent::FocusIn); m_dataStream << newWidget; } } void onApplicationStateChanged(Qt::ApplicationState state) { if (m_recording) { m_dataStream << qint64(QDateTime::currentDateTime().msecsTo(m_startTime)); m_dataStream << qint32(QEvent::ApplicationActivate + state); } } private: QFile m_file; QDataStream m_dataStream; bool m_recording = false; QDateTime m_startTime; QTimer m_timer; }; class Player : public QObject { Q_OBJECT public: Player(QObject *parent = nullptr) : QObject(parent) { } public slots: void play(QString filename) { if (m_file.isOpen()) { return; } m_file.setFileName(filename); if (!m_file.open(QIODevice::ReadOnly)) { return; } m_dataStream.setDevice(&m_file); m_dataStream.setVersion(QDataStream::Qt_5_15); qint64 startTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); while (!m_dataStream.atEnd()) { qint64 timestamp; m_dataStream >> timestamp; qint32 eventType; m_dataStream >> eventType; switch (eventType) { case QEvent::MouseMove: { QPoint pos; m_dataStream >> pos; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [pos]() { QCursor::setPos(pos); }); break; } case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: { int button = eventType - QEvent::MouseButtonPress; QPoint pos; m_dataStream >> pos; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [button, pos]() { QMouseEvent event(QEvent::MouseButtonPress + button, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); qApp->sendEvent(qApp->focusWidget(), &event); }); break; } case QEvent::KeyPress: case QEvent::KeyRelease: { int key = eventType - QEvent::KeyPress; int modifiers; m_dataStream >> modifiers; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [key, modifiers]() { QKeyEvent event(key == 0 ? QEvent::KeyPress : QEvent::KeyRelease, key, Qt::NoModifier, QString(), false, modifiers); qApp->sendEvent(qApp->focusWidget(), &event); }); break; } case QEvent::FocusOut: case QEvent::FocusIn: { QWidget *oldWidget, *newWidget; m_dataStream >> oldWidget >> newWidget; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [oldWidget, newWidget]() { qApp->setActiveWindow(newWidget->window()); qApp->setActiveWindow(newWidget); qApp->setActiveWindow(newWidget->window()); newWidget->setFocus(Qt::OtherFocusReason); }); break; } case QEvent::ApplicationActivate: case QEvent::ApplicationDeactivate: case QEvent::ApplicationStateChange: { int state = eventType - QEvent::ApplicationActivate; int delay = timestamp - startTime; QTimer::singleShot(delay, this, [state]() { qApp->setApplicationState(Qt::ApplicationState(state)); }); break; } default: break; } startTime = timestamp; } m_file.close(); } private: QFile m_file; QDataStream m_dataStream; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; w.show(); Recorder recorder; Player player; QTimer::singleShot(1000, [&]() { recorder.startRecording("record.dat"); }); QTimer::singleShot(5000, [&]() { player.play("record.dat"); }); return a.exec(); } #include "main.moc" ``` 这个示例代码使用了两个类 `Recorder` 和 `Player` 实现了录制和回放功能。`Recorder` 类用于录制鼠标和键盘事件,`Player` 类用于回放录制的事件。在 `main` 函数中,我们创建了一个 `Recorder` 和一个 `Player` 对象,并分别在程序启动后 1 秒和 5 秒后开始录制和回放。录制的数据保存在 `record.dat` 文件中,回放时从该文件中读取数据。 在 `Recorder` 类中,我们使用 `QDataStream` 将鼠标和键盘事件的时间戳、事件类型和事件数据写入到文件中。在鼠标或键盘事件发生时,我们会记录下事件的时间戳、事件类型和事件数据,然后写入到文件中。在 `stopRecording` 函数中,我们停止录制,并断开与 `QApplication` 的信号连接。 在 `Player` 类中,我们使用 `QDataStream` 从文件中读取鼠标和键盘事件的时间戳、事件类型和事件数据,并使用 `QTimer::singleShot` 来模拟鼠标和键盘事件的发生。在鼠标或键盘事件发生时,我们会计算出事件与上一个事件的时间差,然后使用 `QTimer::singleShot` 在相应的时间后模拟事件的发生。在 `play` 函数中,我们通过循环读取文件中的所有事件,并在每个事件发生的时间点模拟事件的发生。 注意:这个示例代码只是一个简单的实现,没有考虑到很多复杂的情况,例如多线程、多窗口、控件状态等。在实际应用中,需要根据具体情况进行修改和完善。

相关推荐

最新推荐

recommend-type

Qt 键盘、鼠标事件的处理

qt、 中鼠标,键盘事件是很重要的,在我们做一些好看并好用的界面是 它们必不可少。
recommend-type

Qt 鼠标/触屏绘制平滑曲线(支持矢量/非矢量方式)

主要介绍了Qt 鼠标/触屏绘制平滑曲线(支持矢量/非矢量方式),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

海思hi3536开发板QT鼠标事件捕获,鼠标移动new.docx

海思hi3536开发板QT鼠标事件捕获,鼠标移动 ,板子上的配置工作。成功显示鼠标和捕获事件, 可以用cat /dev/input/event0查看鼠标移动数据
recommend-type

Qt在vs2019中使用及设置方法

主要介绍了Qt在vs2019中使用及设置方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

Qt实现保存、浏览、预览、打印功能的示例代码

下面小编就为大家分享一篇Qt实现保存、浏览、预览、打印功能的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

云原生架构与soa架构区别?

云原生架构和SOA架构是两种不同的架构模式,主要有以下区别: 1. 设计理念不同: 云原生架构的设计理念是“设计为云”,注重应用程序的可移植性、可伸缩性、弹性和高可用性等特点。而SOA架构的设计理念是“面向服务”,注重实现业务逻辑的解耦和复用,提高系统的灵活性和可维护性。 2. 技术实现不同: 云原生架构的实现技术包括Docker、Kubernetes、Service Mesh等,注重容器化、自动化、微服务等技术。而SOA架构的实现技术包括Web Services、消息队列等,注重服务化、异步通信等技术。 3. 应用场景不同: 云原生架构适用于云计算环境下的应用场景,如容器化部署、微服务
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。