事件和信号Qt的的QGraphicsItem:这是如何* *应该工作?(Events and sig

2019-06-24 10:53发布

像Qt的其他原语,QGraphicsItems可以处理鼠标事件等。 甜! 现在说我需要一个的QGraphicsItem的事件在同一场景中被传播到其他一些QGraphicsItems。 我能想到的,人们可能会接近这个方法有两种:


(A)天真的方法 - 信令

概念:连接与信号加在一起同级QGraphicsItems。 上的QGraphicsItem调用的事件处理程序发出()秒,唤起其他QGraphicItems协调一致的反应。 在此之前,整个Qt框架制订的一般设计模式。

执行:对于原因,我不完全掌握,QGraphicsItems不能发出()信号。 有人建议派生类也从QGraphicsObject继承或许可以解决这个问题。 在我看来,虽然,在QGraphicsItems EMIT()排除可能是对Qt的开发者和,部分有意的设计决策,因此,多重继承可能不是正确的解决方案。

(B)容器级别的事件处理

概念:QGraphicsItems总是存在类型QGraphicsScene的容器的上下文。 在(A)在所述的QGraphicsItem的水平进行处理的事件,而不是由对象从QGraphicsScene继承处理。 该目的还实现用于协调兄弟QGraphicsItems之间响应的逻辑。

执行:QGraphicsScene肯定要处理的事件,否则让他们一路下跌到QGraphicsItems的能力。 QGraphicsScene还提供了用于确定其在它的事情是由位置事件,例如鼠标点击影响itemsAt()方法。 尽管如此,containees之间的容器类中建立了相当多的逻辑协调行动感觉就像未能妥善封装。 不好的做法? 也许吧,但是这似乎是它至少所做的那样一个正式例子 。


问题

  1. 什么是正确的解决方案吗? 如果不是A或B,然后是别的东西,我都没有想到的?
  2. 没有了Qt开发者为什么允许QGraphicsItems接收事件,但不发送信号? 这似乎是一个主要的例外,整个框架使用的设计模式。
  3. 这个问题的一个扩展是QGraphicsItems和更高阶容器类,如主应用程序之间的通信。 如何这意味着需要解决?

Answer 1:

信令是不是QGraphicItem的一部分,因为他们不从的QObject继承。 这是出于性能方面的设计决定,允许非常大的和快速的场景。 如果你决定你真正需要的信号特殊情况下,QGraphicsWidget是为了填补这一空白。 它继承自QObject,让你有QWidget中和的QGraphicsItem功能的混合物。 尽管建议您避免这种情况,如果你的场景甚至适度可观。

这可能是有关你的情况另一种选择是利用sceneEventFilter方法。 您可以为另一组一个项目来接收事件,并决定他们是否应该被传播与否: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qgraphicsitem.html#sceneEventFilter
一个项目可以设置为过滤多个对象。 它可以识别各个项目和事件作出回应。

但是总的来说,你应该充分利用现场的跨越它的对象协调。 这是已经被用于事件模式(现场协调交付的所有事件的项目)。

此外,它似乎是你的选项A是不可能的,因为的QGraphicsItem甚至没有一个EMIT方法。 您需要撰写里面一个QObject实例作为成员,并用它来发射信号。 沿着线的东西myItem.qobject.emit() 否则,你就必须继承QGraphicsObject自己的完全自定义的一个

更新1:解决你的主要的意见更新

您的具体情况与“热角”的矩形。 我看到这是一个自定义的QGraphicsItem。 你可能会继承QGraphicsRectItem,然后撰写孩子热角落里面的物品作为儿童项目( setParentItem() 现在,您的矩形项目知道它的孩子,可以对它们直接作用。 您可以设置矩形项目是为孩子们的sceneEventFilter和直接处理的事件。 没有必要去备份到现场。 让所有这个逻辑住在类。

更新2:解决你的问题补充#3

通讯传播超越了现场的QWidget的有我能想到的几个方法:

  1. 这是一种情况,如果你想使用QGraphicsObject子类作为您的根项目,你可以考虑一下,然后撰写其余对象为儿童(矩形位置,然后将热角为矩形的儿童)。 这将允许对象以发射信号。 为了清楚起见,他们可能仍然可以连接到现场,然后现场的高阶容器将连接到现场。 你将不得不通过案例选择上的情况下这种做法,根据不同的场景的复杂性,以及是否QGraphicsObject上有任何性能影响。 你或许应该避免这种情况,如果你将这些实例的大量。
  2. 你可以定义你的矩形类的回调,为此,现场可以设置。 或者是这样的: graphicsRect.resizedCallback作为一个属性,或者一个setter graphicsRect.setResizedCallback(cbk) 在你的矩形类,你只需调用适当的时候。 如果回调将其设置,它可以用来直接调用一些你的场景。 该矩形类仍然没有这种逻辑的知识。 它只是调用一个回调。

这些只是一些建议。 我敢肯定还有其他的方法。



Answer 2:

我推荐家庭,除非你有相对较少的QGraphicsItems。 我相信QGraphicsItems不是的QObject因为没有与相关的QObject额外开销的某一量。 该框架的QGraphicsView被设计为允许快速插入和许多(例如,数千个)QGraphicsItems的缺失到场景,所以重量较轻的办法是首选。

我想看看养育的QGraphicsItems概念。 QGraphicsItems可以有父母和孩子,这有类似于亲子之间的QObject几个方面的影响。 例如,如果移动父的QGraphicsItem,它的孩子也跟着移动,如果你删除父,其子女将被删除。 您可以使用访问的QGraphicsItem的父QGraphicsItem::parentItem()和儿童使用QGraphicsItem::childItems() 所以,你可以轻松地访问同级的项目是这样的:

QList<QGraphicsItem *> mySiblings = this->parentItem()->childItems();

需要注意的是mySiblings包括this



文章来源: Events and signals in Qt's QGraphicsItem: How is this *supposed* to work?
标签: qt qt4 pyqt4