添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

qt快捷键创建,冲突解决

客户端的工作总是绕不开undo\redo和快捷键的;快捷键事件通常是由键盘事件触发的,它的响应通常和当前激活(focus)的窗口有关;

本文内容主要包括:

qt快捷键创建的方式和四种快捷键属性的意义;

快捷键冲突解决方法;

键盘事件和快捷键事件的关系,部分源码分析;

1:构造

QShortcut::QShortcut(const QKeySequence & key , QWidget * parent , const char * member = nullptr, const char * ambiguousMember = nullptr, Qt::ShortcutContext context = Qt::WindowShortcut)

qkeysequence是一个描述快捷键的类,parent传入依附的父窗口;第三,四个参数传入快捷键触发执行的函数(也可以链接shortcut的activated信号触发);第五个枚举参数描述快捷键作用域;重点描述下第五个参数的意义;

widgetShortcut :父窗口为focus状态时才生效;有时候会出现widget嵌套的情况,当某shortcut的父窗口获取不到焦点时,便不会触发了(通过设置widget的focusPolicy属性,确定焦点获取的策略);该类型的作用域相对最小;

widgetWithChildrenShortcut : 当该窗口的父窗口或者子窗口获取shortcut时,可以触发;这个作用域比第一个大了许多,一条父子窗口链上focus都可以触发,但要注意子窗口不能是顶层窗口或者具有pop-up属性(Qt::windowFlags属性的设置)

windowShortcut :注意的点主要是该类型的shortcut的父对象(parent)必须要设置有qt::Window的窗口属性,不然无法触发;eg:

applicationShortcut 的触发范围最广(只要该应用处于激活状态即可),也最容易产生冲突;尤其是当我们的界面二级窗口众多时候;

2:冲突解决

当界面的二级窗口较多时容易产生快捷键冲突;

例如在mainWindow1若设置有全局快捷键

window按钮弹出二级弹窗,并设有window属性快捷键

window属性的窗口
window窗口的快捷键

这时点击window按钮,窗口显示,快捷键开始作用。这时"A"键盘事件既对应了主窗口的applicationShortcut,又对应了window窗口的快捷键,双方的快捷键就都失效了;

处理方法为:在window的事件过滤器中单独处理快捷键事件,并不把这个事件继续发送给其他的事件过滤器和窗口;事件类型为QEvent::ShortcutOverride

注册
通过事件过滤器对window窗口快捷键事件单独处理

通过打印信息确认事件冲突处理成功;

通过这种方式: 判断键盘事件的组合 并触发相应的 工作函数, 可以解决很多冲突问题;

此处必须提醒下,如果是在主窗口创建了一个QAction的动作用于Menu则在window窗口会产生重复事件;即mainwindow和window都会收到该键盘消息;若要屏蔽掉此时主窗口的响应,将该事件接受掉即可;

将事件接受,不再做进一步处理


3,qt框架键盘事件和其快捷键系统的关系

从调用堆栈和源码结构来看,可以得出的结论是当键盘事件触发后,qt优先把它当作快捷键事件处理(QEvent::ShortcutOverride)(1),这个过程中先给各个事件过滤器处理,最后给接收者处理,若某个事件过滤器return true了,其他的接收者就无法处理到了;

当该事件没有被接受响应时,则当作键盘事件发送给对应窗口(QEvent::KeyEvent)(2);

1
若shortcutoverride事件被accept,键盘事件就不会发出了(return false)

综上从实际开发来讲,如果我们不希望触发键盘事件就要把事件接受掉;如果我们不希望其他的事件过滤器处理到该事件,则在处理时间后返回true,停止对其他事件过滤器的遍历;事件过滤器可以看成责任链模式吧;


笔者用的qt版本为5.9.0,不同版本的堆栈可能不一样;想进一步深入研究的小伙伴就下载一下pdb深入研究吧;

附:键盘事件到事件过滤器

笔者写了一个测试demo,可以玩一下;

----更新

遗漏的一些东西:

QKeySequence抽象来说是qt快捷键描述的类,它的构造可以从按键组合,或从对应的快捷键“文字”而来;值得注意的是,这种文字是有多语言本地化的,例如:

英语的”shift“,QKeySequence::nativeText 为may;

英语的“up“,日语中为一个向上的箭头;

portableText则是用英语字符串描述按键符号,例如:

最后一种方式是用键盘枚举值相加,精确描述,例如:


-----------------------------------温柔分割线---------------------------------------

编辑于 2021-02-13 09:51

文章被以下专栏收录