sqe与ipqc工程师该如何选择(QPointerEvent和QEventPoint是个啥)
sqe与ipqc工程师该如何选择(QPointerEvent和QEventPoint是个啥)在C 中处理与设备无关的事件我已经分叉了 clazy,并添加了一个新的 qevent-accessors 检查,这可能会给你省去一些麻烦:它可以自动应用 "fixits "来摆脱来自事件访问器重命名的废弃警告。QPointerEvent是一个新的抽象类型,适用于所有来自指向设备(鼠标、触摸屏、平板电脑手写笔)的事件。它拥有通用的API,能够以设备无关的方式处理所有这些事件。由于QTouchEvent可以在一个事件中携带多个触摸点,我们将这个概念标准化:每个QPointerEvent都可能代表一个QEventPoint实例的集群(即使大多数事件只携带一个点),因此具有适当的API:point()、point(i)和pointCount()。每个QInputEvent(包括QPointerEvent)都携带一个指向它来自的QInputDevice的指针。这允许事件处理代码以特
Qtitan工具集:
- QtitanRibbon: 遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
- QtitanChart :是一个C 库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。并且支持所有主要的桌面操作系
Qt Quick中鼠标和触摸事件的传递是很复杂的,几年前我们就清楚地意识到,我们需要重构事件继承层次结构,为各种事件类型提供一些通用的API,以便共享更多的传递代码。在Qt 5.8中,我们添加了QQuickpointerEvent和相关的类型,以此作为原型。它们是QObjects;从那时起,QQuickWindow就开始交付这些包装器事件,里面携带着原始事件。现在终于在Qt 6中,我们能够完成QEvent的重构,这样QQuickWindow就不再需要包装器了。与此一起,我们还能够增加一些功能,并修复一些bug。剩下的许多在 Qt 5 中看起来难以解决的 bug 至少在以后应该可以修复。
QPointerEvent和QEventPoint
现在,继承层次结构如下所示:
QPointerEvent是一个新的抽象类型,适用于所有来自指向设备(鼠标、触摸屏、平板电脑手写笔)的事件。它拥有通用的API,能够以设备无关的方式处理所有这些事件。由于QTouchEvent可以在一个事件中携带多个触摸点,我们将这个概念标准化:每个QPointerEvent都可能代表一个QEventPoint实例的集群(即使大多数事件只携带一个点),因此具有适当的API:point()、point(i)和pointCount()。
每个QInputEvent(包括QPointerEvent)都携带一个指向它来自的QInputDevice的指针。这允许事件处理代码以特定设备的方式进行响应,即使在处理合成鼠标事件时也是如此。
每个QEventPoint都有速度。Qt Quick 在 Qt 5 中使用的 Kalman 过滤器已经被移到了 QtGui 中,因此无论事件在哪里传递,都可以得到最近几次移动的平均速度。这使得对速度敏感的行为(如区分慢速拖动和快速轻弹,或对特定的运动方向做出反应)可以不受来自哪个设备的影响。瞬时速度通常对这种目的来说太不稳定了,但如果你需要它,你可以用(globalposition()-globalLastPosition())来计算。/ (timestamp() - lastTimestamp())。
QSinglePointEvent 是另一个抽象类型,它将过去在 QMouseEvent、QTabletEvent、QHoverEvent、QWheelEvent 和其他一些类型中单独且不一致地实现的位置访问器标准化。position()取代了 pos()和 posF(), scenePosition()取代了 windowPos(), globalPosition()取代了 screenPos()。旧的访问器现在仍然存在,但已经废弃:例如,Qt 5 应用程序不会因为处理 QMouseEvent 而遇到 SC 断裂。QEventPoint 取代了 QTouchEvent::TouchPoint,但为了源代码的兼容性,有一个 "using "声明。
我已经分叉了 clazy,并添加了一个新的 qevent-accessors 检查,这可能会给你省去一些麻烦:它可以自动应用 "fixits "来摆脱来自事件访问器重命名的废弃警告。
在C 中处理与设备无关的事件
在Qt中的各个地方,我们现在可以对鼠标、触摸和平板电脑事件(如检测到点击或拖动)做出响应,或者通过迭代QEventPoints,或者只对第一个点做出响应。下面是一个人为的例子,说明QQuickItem子类如何做到这一点。
bool MyItem::event(QEvent *ev) override {
if (ev->isPointerEvent()) {
QPointerEvent *pev = static_cast<QPointerEvent *>(ev);
for (QEventPoint &point : pev->points()) {
switch (point.State()) {
case QEventPoint::State::Pressed:
if (reactToPress(point.position()))
pev->setExclusiveGrabber(point this);
break;
case QEventPoint::State::Updated:
...
}
}
return true;
}
return QQuickItem::event(ev);
}
例如,QQuickFlickable :: childMouseEventFilter()以这种方式工作。这产生了一个有趣的结果:
Flickable现在可以处理触摸了
Qt 5的Flickable只能处理实际的鼠标事件和合成的鼠标事件,有很多开放性的bug。Qt只支持一个鼠标,一个鼠标位置,一个光标(到目前为止,但我们正在努力解决这个问题......),因此你不能用两根手指轻触两个Flickable。如果你触摸了Flickable里面的某个能够处理触摸事件的组件,但是你在允许的方向上拖动你的手指穿过Flickable,它就会使用childMouseEventFilter()从该组件中窃取抓取;但是这涉及到从实际的触摸事件切换到合成鼠标事件,而且还要记住将以下更新作为合成鼠标事件传递给Flickable。各种事情都出了问题。好吧......那些日子结束了,因为Flickable::childMouseEventFilter()不再关心QPointerEvents来自哪个设备。如果你设置了pressDelay,它就能够暂缓实际的触摸按压,然后在定时器过期时重播给里面的项目。是的,现在你也可以用多个手指拖动多个Flickables了。
多点触控虽然仍然不能与其余的只用鼠标的项目(如MouseArea)一起工作,因为这些项目仍然依赖于协同鼠标事件。但可以避免。一般来说:尽量使用事件处理程序而不是MouseArea,因为(正如它的名字所示)它并不是真的要支持任何比鼠标交互更多的东西。
QTabletEvents(来自你的Wacom手写笔、三星S-pen、Apple Pencil等)也只是指针事件,它们携带了一些更多的属性,可以由任何处理鼠标和触摸事件的设备无关代码来处理。但我们会继续努力改善这些体验。我们没有在QQuickItem中为它们添加任何新的虚拟函数,但它们很快就会被交付给QQuickItem::event()。
另一件事我们还在努力,就是让Flickable在笔记本触摸板上表现得更好。很快就会有一个修复方案。
QInputDevice
QInputDevice是一个QObject,它的parent()可以是另一个设备,如果有一个自然的层次结构:例如,X11有主设备和从设备,一个平板电脑手写笔 "属于 "一个特定的平板设备。在其他情况下,父设备只是平台插件中的一个对象,出于内存管理的目的,它拥有该设备。
在没有进行设备发现工作的平台上,QInputEvent::device()从来不是空的,而可能是取自QInputDevice::primaryKeyboard()或QPointingDevice::primaryMouse()的通用实例。不过触摸屏设备是独一无二的,我们在Qt 5中已经这样做了。
QInputDevice::seatName()对应于Wayland的 "座位 "概念:一个用户正在使用的一组设备。到目前为止,对多座位的支持还很少,但随着时间的推移,它将会得到改进。如果您配置了一个多指针X服务器,您可以在不同的设备上看到不同的座位名称,但这些名称是由xcb插件中的xinput ID自动生成的。在Wayland合成器上,如Sway,可以给座位任意命名;我们计划Qt最终会与之合作。
$ xinput list
Virtual core pointer id=2 [master pointer (3)]
Virtual core XTEST pointer id=4 [slave pointer (2)]
ZSA Technology Labs ErgoDox EZ Mouse id=11 [slave pointer (2)]
ZSA Technology Labs ErgoDox EZ Consumer Control id=13 [slave pointer (2)]
Logitech MX Master 2S id=15 [slave pointer (2)]
Virtual core keyboard id=3 [master keyboard (2)]
Virtual core XTEST keyboard id=5 [slave keyboard (3)]
Power Button id=6 [slave keyboard (3)]
Power Button id=7 [slave keyboard (3)]
Sleep Button id=8 [slave keyboard (3)]
UVC Camera (046d:0992) id=9 [slave keyboard (3)]
ZSA Technology Labs ErgoDox EZ id=10 [slave keyboard (3)]
ZSA Technology Labs ErgoDox EZ System Control id=12 [slave keyboard (3)]
ZSA Technology Labs ErgoDox EZ Keyboard id=14 [slave keyboard (3)]
ZSA Technology Labs ErgoDox EZ Consumer Control id=16 [slave keyboard (3)]
Logitech MX Master 2S id=17 [slave keyboard (3)]
aux pointer id=22 [master pointer (23)]
Microsoft Microsoft Optical Mouse by Starck id=19 [slave pointer (22)]
aux XTEST pointer id=24 [slave pointer (22)]
aux keyboard id=23 [master keyboard (22)]
Apple Inc Apple Keyboard id=20 [slave keyboard (23)]
Apple Inc Apple Keyboard id=21 [slave keyboard (23)]
aux XTEST keyboard id=25 [slave keyboard (23)]
$ qtdiag
Qt 6.0.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 10.2.0) on "xcb"
OS: Arch Linux [linux version 5.9.11-arch2-1]
...
Input devices: 23
QInputDevice::DeviceType::Mouse "Virtual core pointer" seat: "30002" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "Virtual core keyboard" seat: "30002" capabilities:
QInputDevice::DeviceType::Mouse "aux pointer" seat: "170016" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "aux keyboard" seat: "170016" capabilities:
QInputDevice::DeviceType::Mouse "Virtual core XTEST pointer" seat: "30002" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "Virtual core XTEST keyboard" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "Power Button" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "Power Button" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "Sleep Button" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "UVC Camera (046d:0992)" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "ZSA Technology Labs ErgoDox EZ" seat: "30002" capabilities:
QInputDevice::DeviceType::Mouse "ZSA Technology Labs ErgoDox EZ Mouse" seat: "30002" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "ZSA Technology Labs ErgoDox EZ System Control" seat: "30002" capabilities:
QInputDevice::DeviceType::Mouse "ZSA Technology Labs ErgoDox EZ Consumer Control" seat: "30002" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "ZSA Technology Labs ErgoDox EZ Keyboard" seat: "30002" capabilities:
QInputDevice::DeviceType::Keyboard "ZSA Technology Labs ErgoDox EZ Consumer Control" seat: "30002" capabilities:
QInputDevice::DeviceType::Mouse "Logitech MX Master 2S" seat: "30002" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "Logitech MX Master 2S" seat: "30002" capabilities:
QInputDevice::DeviceType::Mouse "Microsoft Microsoft Optical Mouse by Starck" seat: "170016" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "Apple Inc Apple Keyboard" seat: "170016" capabilities:
QInputDevice::DeviceType::Keyboard "Apple Inc Apple Keyboard" seat: "170016" capabilities:
QInputDevice::DeviceType::Mouse "aux XTEST pointer" seat: "170016" capabilities: Position Scroll Hover
QInputDevice::DeviceType::Keyboard "aux XTEST keyboard" seat: "170016" capabilities:
QInputDevice :: availableVirtualGeometry()旨在告诉您该设备可以访问虚拟桌面的哪个区域。例如,您可能正在使用带有外部显示器的触摸屏笔记本电脑:那么触摸屏的QPointingDevice :: availableVirtualGeometry()应该与屏幕的QScreen :: geometry()相同。Wacom数位板可以映射到小于整个屏幕的区域,以提高绘图精度(使用xinput或特定于操作系统的控制面板)。但是同样,这项工作尚未在所有受支持的平台上完成。
合成鼠标事件
合成鼠标事件仍然存在,尽管我们现在正试图减少对它们的依赖。
QEvent::spontaneous()是我们区分OS产生的事件和合成事件的最古老的方法,但它并不适合区分合成鼠标事件。在Qt 5中,增加了QMouseEvent::source()来帮助你区分由其他设备、操作系统、Qt或应用程序合成的鼠标事件;但后来我们发现,假设这样的事件是由触摸点合成的,既诱人又错误。(例如,它可能是由QTabletEvent合成的。)所以我们建议现在使用event->device()->type()和/或pointerDevice()->pointerType()来区分这些事件。当一个QMouseEvent从其他类型的事件中合成时,设备实例保持不变,这样你就可以知道它到底来自哪里。
分类日志
自从几年前增加了分类日志后,我们在Qt中增加了越来越多的内部日志,(在qtbase和qtdeclarative中git grep Q_LOGGING_CATEGORY会发现很多对调试Qt Quick应用很有用的)。对于排除鼠标和触摸交互问题来说,最有用的类别是qt.pointer.grab,因为grab转换是大多数此类问题的症状或原因。但还有更多:你可以在QPA级别、QtGui级别、QQuickWindow中、向项目和/或处理程序传递过程中记录事件;你还可以在各种项目和处理程序中记录交互的各个方面。
我可能会在以后的文章中写更多关于抓取和接受事件的技术细节。
点击下方“了解更多”获取更新详情