让QGraphicsItemGroup中的item处理自己的事件
来源:互联网 发布:单片机 延时 远离 编辑:程序博客网 时间:2024/04/28 14:28
简述
QGraphicsItem 分组比较简单,但在分组之后 group 中的 QGraphicsItem 无法捕获自己的相关事件(例如:鼠标事件、键盘事件),实际接受消息对象为 QGraphicsItemGroup。那么,如何处理呢?
- 简述
- 处理方式
处理方式
处理方式有两种:
- 方式一,也是最简单的一种:
void QGraphicsItem::setHandlesChildEvents(bool enabled)
如果 enabled 为 true,QGraphicsItemGroup 将处理其所有子 item 的所有事件(即,其任何子 item 的所有事件都发送到此 item),例如:鼠标点击子 item 的事件不会被子 item 自身处理;否则,如果 enabled 为 false,QGraphicsItemGroup 将只处理自己的事件,不会阻止子 item 的事件,并让子 item 处理自己的事件。
根据官方文档描述,该函数参数的默认值为 false。经过实验,重写鼠标事件、键盘事件之后,会发现依然会阻止子 item 的事件,究竟为何?难道是文档有误?
当然不会,打开 QGraphicsItemGroup 的源码,可以发现:
QGraphicsItemGroup::QGraphicsItemGroup(QGraphicsItem *parent) : QGraphicsItem(*new QGraphicsItemGroupPrivate, parent){ setHandlesChildEvents(true);}
在 QGraphicsItemGroup 的构造函数中就这一行代码,也正是我们要找的答案!
所以,要让 QGraphicsItemGroup 中的 item 处理自己的事件,还需要在构造 group 后,再手动调用:
QGraphicsItemGroup::setHandlesChildEvents(false);
这一行代码即可。
- 方式二,
bool QGraphicsItem::sceneEvent(QEvent *event)
该虚函数接收到此 item 的事件。重新实现这个函数,在事件被分派到专门的事件处理程序之前拦截事件 contextMenuEvent()、focusInEvent()、focusOutEvent()、hoverEnterEvent()、hoverMoveEvent()、hoverLeaveEvent()、keyPressEvent()、keyReleaseEvent()、mousePressEvent()、mouseReleaseEvent()、mouseMoveEvent()、和 mouseDoubleClickEvent()。
如果事件被识别和处理,则返回 true;否则(例如,如果事件类型未被识别),则返回 false。
event 是拦截的事件。
这样看来,sceneEvent() 接收一个 item 的所有事件,非常类似于 QWidget::event()。
既然如此,重写此函数也可以让 QGraphicsItemGroup 中的 item 处理自己的事件。
#include <QGraphicsEllipseItem>#include <QEvent>#include <QGraphicsSceneMouseEvent>#include <QKeyEvent>#include <qDebug>class CustomItem : public QGraphicsEllipseItem{public: CustomItem(QGraphicsItem *parent = 0) { setFlag(QGraphicsItem::ItemIsFocusable); }protected: // 按键按下事件 void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE { Q_UNUSED(event); qDebug() << "keyPressEvent"; } // 按键释放事件 void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE { Q_UNUSED(event); qDebug() << "keyReleaseEvent"; } // 鼠标按下事件 void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE { Q_UNUSED(event); qDebug() << "mousePressEvent"; } // 鼠标按下事件 void mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE { Q_UNUSED(event); qDebug() << "mouseMoveEvent"; } // 鼠标释放事件 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE { Q_UNUSED(event); qDebug() << "mouseReleaseEvent"; } // 处理上述事件 bool sceneEvent(QEvent *event) Q_DECL_OVERRIDE { switch (event->type()) { case QEvent::GraphicsSceneMousePress: mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); break; case QEvent::GraphicsSceneMouseRelease: mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); break; case QEvent::GraphicsSceneMouseMove: mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); break; case QEvent::KeyPress: keyPressEvent(static_cast<QKeyEvent *>(event)); break; case QEvent::KeyRelease: keyReleaseEvent(static_cast<QKeyEvent *>(event)); break; default: break; } event->accept(); return true; }};
显然,大多数情况下,正确的姿势应该选择方式一,因为对我们来说更简单,方式二则需要为每一个自定义 item 都去实现 sceneEvent()。
- 让QGraphicsItemGroup中的item处理自己的事件
- ListView 中 item的事件处理
- ListView中的Button事件及ListView Item焦点的冲突处理
- ListView的Item中的按钮点击事件
- ListView中的滑动事件与Item的点击事件
- ListView中的item中的Onclick事件的优化
- listview 的item拿不到点击事件的处理方法
- listview的item点击事件不触发的处理
- android listview系列之item的点击事件及item布局中的点击事件(四)
- ListView中item点事件和item中的控件点击事件冲突的简易解决方法
- 屏蔽listview中的item点击事件,但不屏蔽item子控件的点击事件
- android abslistview item点击事件无响应的处理方式
- Android如何处理列表控件的item同时点击事件
- Android XRecyclerView最简单的item点击事件处理
- listview中的item和button的点击事件的冲突
- listview中的item增加事件
- RecyclerView中的item点击事件
- ListView中的item点击事件
- 使用Session防止表单重复提交
- tomcat-7.0源码安装配置
- 2016年12月7日学习总结----今日知识点总结
- 运放知识
- 系统学习Unix网络编程
- 让QGraphicsItemGroup中的item处理自己的事件
- 【codeforces 557C Arthur and Table】+ 思维
- 复杂的c-c++声明
- tensorflow 在 win7 64位的配置
- Word图标不能正常显示
- 【已解决】macOS10.12.1的gitk报错,无法打开
- Junit使用过程中需要注意的诡异bug以及处理办法
- 最短路算法(1)- bellman ford算法
- Abstract Factory(抽象工厂)实践