QGraphicsItem如何使用信號/槽

簡述

對於 QGraphicsItem 來說,信號/槽和屬性機制不是它的一部分,因爲它不繼承自 QObject。這是一個出於性能考慮的設計決策,允許比較大的場景以及快速的交互。

特殊情況下,如果真的需要使用信號/槽,可以使用 QObject 的信號/槽和屬性機制來擴展 QGraphicsItem。

繼承自 QObject 和 QGraphicsItem

這種方式屬於多繼承,也是最容易想到的方式。

class CustomItem : public QObject, public QGraphicsItem
{
    Q_OBJECT

public:
    explicit CustomItem(QGraphicsItem *parent = 0);
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);

Q_SIGNALS:
    void mySignal();

public Q_SLOTS:
    void mySlot();
    ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

繼承自 QGraphicsObject

QGraphicsObject 類爲需要信號/槽和屬性的所有 items 提供一個基類,將 QGraphicsItem 的許多基本 setters 和 getters 映射到屬性,併爲其中的許多添加了通知信號。

由於 QGraphicsObject 繼承自 QObject 和 QGraphicsItem,所以,上述的自定義 item 可以變成這樣:

class CustomItem : public QGraphicsObject
{
    Q_OBJECT

public:
    explicit CustomItem(QGraphicsItem *parent = 0);
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);

Q_SIGNALS:
    void mySignal();

public Q_SLOTS:
    void mySlot();
    ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

這時,很多人會陷入一種誤區,認爲上述兩種方式一樣,而且“繼承自 QGraphicsObject”更簡單。真的是這樣嗎?不妨分析一下!

性能差異

正如上面所說,由於 QGraphicsObject 繼承自 QObject 和 QGraphicsItem,所以其擁有 QObject 和 QGraphicsItem 的基本特性。除此之外,它還提供了額外的信號,例如:enabledChanged()、opacityChanged()、xChanged()、yChanged() 等等。

也就是說,如果使用 QGraphicsObject,會有一些不感興趣的信號自動發射。例如,調用 QGraphicsItem::setPos(),會執行以下代碼:

void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
{
    Q_Q(QGraphicsItem);
    inSetPosHelper = 1;
    if (scene)
        q->prepareGeometryChange();
    QPointF oldPos = this->pos;
    this->pos = pos;
    dirtySceneTransform = 1;
    inSetPosHelper = 0;
    if (isObject) {  // 額外的開銷
        if (pos.x() != oldPos.x())
            emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
        if (pos.y() != oldPos.y())
            emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

這時,QGraphicsObject 會有額外的開銷(發射 xChanged()、yChanged() 信號)。所以,性能如何?用事實說話!

雖然上述方式均繼承自 QObject,來自 QObject 的內存開銷不可避免,但 QGraphicsObject 效率明顯更低,因爲其有額外的信號,如果創建許多 QGraphicsObject,可能會顯着影響性能。

原文:http://blog.csdn.net/liang19890820/article/details/53643700

博文索引  持續更新中。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章