当前位置: 首页 > news >正文

Qt5.14.2 全面解锁Qt5事件处理的精髓


上一篇博文中,我们从高空中俯瞰了Qt5事件编织的壮阔进程。无论是最普通的鼠标点击,还是最先进的多点触控手势,抑或是跨越线程的事件传递,Qt5都为开发者们提供了一整套完备的事件处理方案和强大工具链,只等着你来施展渔阳鼎力,尽情驰骋拳打脚踢。


现在,就让我们放眼脚下,深入研究其中最为普通而又至关重要的鼠标和键盘事件吧! 毕竟,它们就如同GUI应用程序的肢体神经,承载着人机交互的一切。那么,Qt5是如何帮助我们精准捕捉和优雅响应这些来自用户的交互指令呢?让我们拨开重重迷雾,一一揭晓!


一、鼠标键盘事件


1、指尖下的强力舵手 - 鼠标事件的操纵杆

鼠标可以说是GUI程序中最常见和最主要的交互方式了。Qt5提供了多个类来帮助我们精准无误地处理各种鼠标事件,如QMouseEvent、QHoverEvent、QTabletEvent等。而QWidget及其派生类中的鼠标事件处理函数,就是驾驶这一切的高级操纵杆:

void MyWidget::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {// 处理鼠标左键按下...}
}void MyWidget::mouseMoveEvent(QMouseEvent *event)
{// 处理鼠标移动...
}void MyWidget::mouseReleaseEvent(QMouseEvent *event) 
{if (event->button() == Qt::RightButton) {// 处理鼠标右键释放...}
}

无论用户何时点击鼠标按钮、移动鼠标或停留在窗口区域,这些事件首先会分别进入对应的事件处理函数。我们只需要重新实现这些函数,根据QMouseEvent提供的坐标、按钮、修饰键等信息,编写自己的业务逻辑,就可以完全掌控鼠标交互了。


别忘了mousePressEvent和mouseReleaseEvent还有一个双击形式的兄弟 - mouseDblClickEvent,用于处理鼠标双击。另外,QHoverEvent也是判断鼠标悬停的重要线索。


2、神剑勾魂 指尖乾坤 - 键盘敲击的分秒必争


键盘输入是另一种重要的GUI交互方式,尤其在输入文本信息或快捷键操作时。而Qt5通过QKeyEvent和QShortcutEvent等类,也为开发者提供了驾驭键盘指令的利器:

void MyWidget::keyPressEvent(QKeyEvent *event)
{if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {// 处理回车键被按下...} else if (event->matches(QKeySequence::Copy)) {// 处理复制快捷键被按下...}
}void MyWidget::keyReleaseEvent(QKeyEvent *event)
{// 处理按键释放...
}void MyWidget::customShortcut()
{QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this);connect(shortcut, &QShortcut::activated, this, &MyWidget::handleCustomShortcut);
}

通过重写keyPressEvent和keyReleaseEvent方法,我们就能拦截并响应用户的每一次按键动作。QKeyEvent提供了被按下的按键信息,我们可以方便地进行判断和处理。

而对于常用的快捷键组合,如复制粘贴等,Qt5还为我们提供了QKeySequence的高级工具,使用它可以非常方便地检查按键是否匹配快捷键。

当然,有时候我们也需要自定义快捷键,这时就可以利用QShortcut来创建全局或上下文快捷键。只需将想要的键序列和处理函数连接起来,就可以完成快捷键操作了。


3、挥剑斩浪 壹气呵成 - 鼠标键盘并重的艺术馆


在现代的GUI应用中,鼠标和键盘输入往往是并重出击的。比如在文本编辑器中,我们可能先是使用鼠标进行区域选择,再通过键盘输入命令执行操作。再比如在绘图软件里,我们需要结合鼠标与键盘输入,来完成多种交互动作。

但是鼠标和键盘事件最终都需要在同一个事件处理中完成,这就要求我们设计出更加复杂的交互逻辑。幸运的是,Qt5为我们提供了多个辅助工具和技术:

// 使用按键修饰键
if (event->modifiers() & Qt::ShiftModifier) {// Shift键被按下时执行的逻辑
}// 鼠标光标设置
if (someCondition) {setCursor(Qt::PointingHandCursor);
} else {setCursor(Qt::ArrowCursor);
}// 焦点策略
setFocusPolicy(Qt::ClickFocus); // 单击时自动获取键盘焦点

首先是修饰键,像Shift、Ctrl、Alt等常用键被按下时,会体现在鼠标或键盘事件的modifiers()中。利用这一点,我们就能轻松地对组合键做出响应。

其次,Qt还提供了丰富的鼠标光标形状,可以根据不同状态和场景,方便地切换鼠标光标的样式,为用户提供更多视觉线索。

最后,焦点策略也是整合鼠标和键盘事件的重要一环。我们可以控制键盘焦点在窗口间的移动规则,使之与鼠标交互相呼应,为用户提供一致的体验。


二、触控手势


1、天地鼓动 掌跆指挥 - 触控手势交互的新时代

随着智能手机、平板电脑的普及,触控和手势这种全新的交互方式越来越受到重视。传统的鼠标和键盘在移动设备上已经无法满足用户需求,因此Qt5也及时跟上了这股潮流,为开发者提供了处理触控和手势事件的完备支持。

bool MyWidget::event(QEvent *event)
{if (event->type() == QEvent::Gesture) {// 处理手势事件QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);qDebug() << "Gesture event detected with" << gestureEvent->gestures().size() << "gestures";for (QGesture *gesture : gestureEvent->gestures()) {if (QPinchGesture *pinch = qobject_cast<QPinchGesture *>(gesture)) {// 捕捉到pinch手势qreal scaleFactor = pinch->totalScaleFactor();if (pinch->state() == Qt::GestureStarted) {lastScaleFactor = scaleFactor;} else if (pinch->state() == Qt::GestureUpdated) {// 更新缩放比例updateScaleFactor(scaleFactor / lastScaleFactor);lastScaleFactor = scaleFactor;}}}return true;} else if (event->type() == QEvent::TouchBegin) {// 处理触摸按下事件...}return QWidget::event(event);
}

这段代码展示了如何在event()函数中捕获手势事件和触摸事件。QGestureEvent包含了一个或多个QGesture对象,用于描述发生的手势类型,如QPinchGesture代表了两指缩放手势。

开发者可以遍历QGestureEvent中的所有手势对象,识别出自己感兴趣的手势类型,并根据手势的状态和属性值编写响应逻辑。

除了手势事件,还有专门的QTouchEvent类用于获取原始的多点触摸信息,如按下、移动、释放等。结合这两种事件类型,就能实现丰富的触控手势交互体验了。


三、云穷野极 水到渠成 - 纵横多线程也能游刃有余


在现代计算机系统中,单线程的计算能力已经无法满足日益复杂的需求。而Qt5本身就是一个多线程友好的框架,它对线程间事件的传递有着深度的支持和优化。

// 工作线程
QThread workerThread;
QObject *myObject = new MyObject;
myObject->moveToThread(&workerThread);
workerThread.start();// 发送自定义事件到工作线程
QMetaObject::invokeMethod(myObject, "handleEvent", Q_ARG(QString, "Hello from main thread!"));class MyObject : public QObject
{Q_OBJECT
public slots:void handleEvent(const QString &message){qDebug() << "Received event from main thread:" << message;}
};// GUI线程 
void setupGUI()
{QLabel *label = new QLabel;label->show();// 从工作线程更新UIQMetaObject::invokeMethod(label, "setText", Q_ARG(QString, "New text"), Qt::QueuedConnection);
}

这个示例展示了如何在Qt应用中横跨多线程。首先我们创建了一个工作线程,并让MyObject对象在该线程中运行。然后通过QMetaObject::invokeMethod方法,我们就能安全地将事件对象或信号发送到目标线程中。


值得注意的是,invokeMethod有多种连接类型可选,Qt::QueuedConnection可以将目标方法调用安全地加入事件队列,确保跨线程调用的安全性。

在上例中,我们还展示了如何利用invokeMethod从非GUI线程更新UI。只需以Qt::QueuedConnection的方式调用UI组件的方法,就能避免跨线程问题。

通过Qt提供的这些工具,我们就能轻松驾驭多线程开发中的种种复杂情况,毫无后顾之忧。当然,多线程开发本身就是一个贯穿始终的重要主题,我们后续还会专门就此进行更深入的探讨。


四、海阔凭鱼跃 天高任鸟飞 - 你终将驾驭住这对强将


通过本篇博文,我们系统地学习了Qt5下如何高效地处理鼠标和键盘事件。从最基本的事件处理函数入手,到组合键、光标和焦点策略的高级特性,Qt5都为开发者们提供了一整套强大而易用的武器库。


我们今天的旅程仅仅揭开了事件处理的一角。但放眼Qt的广阔天地,却有太多更高境界等着我们去开拓和征服。勇敢前行吧,未来属于勇猛者! 下一期博文,我将为您开启全新的征程,让我们共同攀登事件编程的巅峰!


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Partisia Blockchain:如何做到兼顾隐私、高性能和可拓展?
  • PHP页面如何实现设置独立访问密码
  • tewa-707e光猫超级密码获取方法
  • Lua热更新(xlua)
  • 今日讲讲路由配置
  • Docker搭建LNMP环境实战(04):安装VMwareTools共享文件夹
  • Unity 计算两个日期的时间差(含绝对值计算方法)
  • Linux相关命令(1)
  • Flink 学习资料
  • NO9 蓝桥杯单片机实践之串口通信的使用
  • 《适配器模式(极简c++)》
  • 基于 Linux 的更新版 MaxPatrol VM 可扫描 Windows
  • 时序预测 | Matlab实现BiTCN-BiLSTM双向时间卷积神经网络结合双向长短期记忆神经网络时间序列预测
  • chatgpt正面案例合集
  • YOLOv9改进策略:IoU优化 | Wasserstein Distance Loss,助力小目标涨点
  • [nginx文档翻译系列] 控制nginx
  • [译] 怎样写一个基础的编译器
  • [译]前端离线指南(上)
  • angular2 简述
  • Flex布局到底解决了什么问题
  • Laravel Telescope:优雅的应用调试工具
  • mysql 数据库四种事务隔离级别
  • Python_网络编程
  • quasar-framework cnodejs社区
  • SpriteKit 技巧之添加背景图片
  • unity如何实现一个固定宽度的orthagraphic相机
  • 安卓应用性能调试和优化经验分享
  • 关于字符编码你应该知道的事情
  • 如何编写一个可升级的智能合约
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 数据结构java版之冒泡排序及优化
  • 与 ConTeXt MkIV 官方文档的接驳
  • Mac 上flink的安装与启动
  • 回归生活:清理微信公众号
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #07【面试问题整理】嵌入式软件工程师
  • #Linux(make工具和makefile文件以及makefile语法)
  • #大学#套接字
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (简单) HDU 2612 Find a way,BFS。
  • (六)Hibernate的二级缓存
  • (五)关系数据库标准语言SQL
  • (正则)提取页面里的img标签
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)winform之ListView
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • ****Linux下Mysql的安装和配置
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .net中生成excel后调整宽度
  • [AIGC] Java 和 Kotlin 的区别