QGraphicsItem如何使用信号/槽

简介: 简述对于 QGraphicsItem 来说,信号/槽和属性机制不是它的一部分,因为它不继承自 QObject。这是一个出于性能考虑的设计决策,允许比较大的场景以及快速的交互。特殊情况下,如果真的需要使用信号/槽,可以使用 QObject 的信号/槽和属性机制来扩展 QGraphicsItem。简述继承自 QObject 和 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();
    ...
};

继承自 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();
    ...
};

这时,很多人会陷入一种误区,认为上述两种方式一样,而且“继承自 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();
    }
}

这时,QGraphicsObject 会有额外的开销(发射 xChanged()、yChanged() 信号)。所以,性能如何?用事实说话!

虽然上述方式均继承自 QObject,来自 QObject 的内存开销不可避免,但 QGraphicsObject 效率明显更低,因为其有额外的信号,如果创建许多 QGraphicsObject,可能会显着影响性能。

目录
相关文章
|
7月前
QT自定义信号,信号emit,信号参数注册
使用signals声明返回值是void在需要发送信号的地方使用emit 信号名字(参数)进行发送在需要链接的地方使用connect进行链接ct进行链接。
77 0
QT自定义信号,信号emit,信号参数注册
|
7月前
|
Linux
网络编程之 信号捕捉器(函数指针与回调函数)(1)
接着我们的信号说下去 之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何注册信号捕捉,以及信号捕捉器的妙用。
73 1
|
7月前
|
Unix
网络编程之 信号捕捉器(函数指针与回调函数)(2)
sigaction()函数 前面我们讲到的内容已经足以用来防止僵尸进程生成的代码。之所以博主还要介绍sigaction()函数是因为它类似于signal()函数,而且完全可以代替后者,也更稳定(主要是书上介绍到了
70 1
|
2月前
(8)Qt中的自定义信号
本文介绍了如何在Qt框架中创建和使用自定义信号,并通过一个父子窗口切换的示例来展示自定义信号的实现和应用。
103 3
(8)Qt中的自定义信号
|
4月前
【qt】QTcpSocket相关的信号
【qt】QTcpSocket相关的信号
27 0
|
5月前
|
Python
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。
|
5月前
|
C++
Qt中的信号与槽如何学习?(包括自定义信号)这篇文章告诉你
以现实中的事件来举例的话,例如有两把不同颜色的信号枪,分别是红色,绿色,打响不通颜色的信号枪会触发不同的槽发生,比如说打响红色这个人就跑步,绿色就走步,但是还有一个很重要的机制,那就是连接,我们需要把信号枪去跟这个人的动作连接起来。 如果上面理解没问题的话我们可以把信号和槽看成两个工具,我们最重要的是如何去把这两个工具连接起来。 它的作用可以让我们更加灵活的去使用不同窗口间的切换以及某些事件的连接。
112 0
《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用
《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用
903 0
《QT从基础到进阶·二十一》QGraphicsView、QGraphicsScene和QGraphicsItem坐标关系和应用
|
缓存 前端开发 异构计算
Vsync信号和View绘制流程的关系
Vsync信号和View绘制流程的关系
252 0