QGraphicsItem如何使用信号/槽

简述

对于 QGraphicsItem 来说,信号/槽和属性机制不是它的一部分,因为它不继承自 QObject。这是一个出于性能考虑的设计决策,允许比较大的场景以及快速的交互。

特殊情况下,如果真的需要使用信号/槽,可以使用 QObject 的信号/槽和属性机制来扩展 QGraphicsItem。

  • 简述
  • 继承自 QObject 和 QGraphicsItem
  • 继承自 QGraphicsObject
  • 性能差异

继承自 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,可能会显着影响性能。

时间: 2024-11-02 05:17:37

QGraphicsItem如何使用信号/槽的相关文章

Qt学习之路(9):深入了解信号槽

槽函数和普通的C++成员函数没有很大的区别.它们也可以使virtual的:可以被重写:可以使public.protected或者 private的:可以由其它的C++函数调用:参数可以是任何类型的.如果要说区别,那就是,槽函数可以和一个信号相连接,当这个信号发生时,它可以被自动调用. connect()语句的原型类似于: connect(sender, SIGNAL(signal), receiver, SLOT(slot)); 这里,sender和receiver都是QObject类型的,si

Qt学习之路(4):初探信号槽

看过了简单的Hello, world! 之后,下面来看看Qt最引以为豪的信号槽机制! 所谓信号槽,简单来说,就像是插销一样:一个插头和一个插座.怎么说呢?当某种事件发生之后,比如,点击了一下鼠标,或者按了某个按键,这时,这个组件就会发出一个信号.就像是广播一样,如果有了事件,它就漫天发声.这时,如果有一个槽,正好对应上这个信号,那么,这个槽的函数就会执行,也就是回调.就像广播发出了,如果你感兴趣,那么你就会对这个广播有反应.干巴巴的解释很无力,还是看代码: #include <QtGui/QAp

no such signal-QT多线程信号槽没有响应

问题描述 QT多线程信号槽没有响应 程序逻辑很简单,就是让一个独立线程发送一个信号,UI线程的槽响应,但是运行报错居然是找不到信号 No such signal ,但是编译可以通过,moc文件也有这个信号.大侠们指点一下子,谢谢 #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui-&g

多线程中的信号/槽

作者: 柴树杉[翻译] (chaishushan@gmail.com) 日期: 2008-01-05 于武汉 注解: 该文档根据Threading, Signals/Slots翻译,依照创作公用约定发布. 开始 在许多应用中都会遇到非常耗时的运算,在进行该类型运算时常常会影响程序正常的消息处理. 为了处理上述问题,我们可以将耗时的运算从GUI线程中移出来,单独放到一个work线程中. 这样的话,GUI则可以保持时刻响应. 下面的例子中,我们将演示如何运用多线程.在一个work线程中将完成绘制五角

信号槽库:sigslot.h和sigc++使用

用qt的知道,qt有方便简单的信号槽机制,但需要专门的qt工具处理. 如果想直接使信号槽就可以使用sigslot库,或者sigc++库,或者boost中的signals,这里介绍sigslot和sigc++库. sigslot.h:只有一个头文件,使用简单方便. sigc++:包含文件多,但功能更强大. sigslot库 官方地址 http://sigslot.sourceforge.net/ 在vs2013中使用 包含头文件 #include "sigslot.h" 1 1 改动:

PyQt5 笔记(05):信号/槽

  PyQt 的很多类都内置了信号和槽.下图是 Qt 官方文档对 QThread 类中包含的信号/槽的描述:       一.信号/槽 都是内置的 请看一个最简单的程序: 按钮点击后,窗口关闭                 代码: class Test(QDialog): def __init__(self, parent=None): super().__init__(parent) btn = QPushButton('关闭', self) btn.clicked.connect(self

qt 信号与槽的发送和接收

问题描述 qt 信号与槽的发送和接收 . . . . 最后结果打印不出来... 解决方案 信号和槽函数做了绑定了吗? 解决方案二: 楼主你connect的是&t发送的fasong(QString)信号 而你代码里面是this->fasong(zhi); ps:这个t是啥.... 解决方案三: 关于Qt信号/槽的参数类型Qt之信号与槽关于Qt中信号槽机制

在Qt Creator 和在 vs2012 里添加信号和槽

Qt  的窗口部件通过发射信号(signal)来表明一个用户的动作已经发生了或者是一个状态已经改变了. 如点击一个QPushButton时,按钮会发送一个clicked()信号,信号可以与函数(在qt里称做槽slot)相连接 可以把信号理解为c#里的事件 在vs2012里和在Qt Creator里添加信号和槽不一样,这里把两种环境下怎么添加详细说明一下   1.在vs2012里添加信号和槽 新建一个qt的项目QtDemo   在qtdeom.h里添加槽 private slots: void B

自定义QGraphicsItem

简述 QGraphicsItem 是场景中 item 的基类.图形视图提供了一些典型形状的标准 item,例如:矩形 ( QGraphicsRectItem ).椭圆 ( QGraphicsEllipseItem ) .文本项 ( QGraphicsTextItem ).当这些不满足需求时(例如:在一些复杂的工作流场景中),往往需要自定义,通常的做法就是继承 QGraphicsItem. 简述 自定义 QGraphicsItem Bounding Rect 和 Shape 参照模型 使用示例 效