QObject_other

发布时间:2024年01月11日

QObject

属性定义

自定义属性我用到的较少,只在自定义键盘时用到了。
属性的行为类似于类数据成员,但它们具有可通过元对象系统访问的附加特性

Q_PROPERTY关键字
定义语法:
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL]
[REQUIRED])

#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)



class A:public QObject
{
    Q_OBJECT
public:
    Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)
    Q_PROPERTY(qreal spacing MEMBER m_spacing NOTIFY spacingChanged)
    Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged)
signals:
    void colorChanged();
    void spacingChanged();
    void textChanged(const QString &newText);

private:
    QColor  m_color;
    qreal   m_spacing;
    QString m_text;
}

bool setProperty(const char *name, const QVariant &value)

如果属性是Q_PROPERTY定义的,设置属性值成功返回true,否则返回false
如果属性不是Q_PROPERTY定义的,则动态的新增属性并且返回false

bool QObject::setProperty(const char *name, const QVariant &value)
{
    Q_D(QObject);
    const QMetaObject* meta = metaObject();//获取元对象
    if (!name || !meta)
        return false;

    int id = meta->indexOfProperty(name);//元对象中查找静态属性
    if (id < 0) {
        if (!d->extraData)
            d->extraData = new QObjectPrivate::ExtraData;

        const int idx = d->extraData->propertyNames.indexOf(name);//静态属性没找到,在动态设置的属性里面找

        if (!value.isValid()) {
            if (idx == -1)
                return false;
            d->extraData->propertyNames.removeAt(idx);
            d->extraData->propertyValues.removeAt(idx);
        } else {
            if (idx == -1) { //动态设置的属性里面也没有找到
                d->extraData->propertyNames.append(name);//新增属性
                d->extraData->propertyValues.append(value);//新增属性值
            } else {
                //动态设置的属性里面找到了
                if (value.userType() == d->extraData->propertyValues.at(idx).userType()
                        && value == d->extraData->propertyValues.at(idx))
                    return false;
                d->extraData->propertyValues[idx] = value;//修改属性值
            }
        }

        QDynamicPropertyChangeEvent ev(name);
        QCoreApplication::sendEvent(this, &ev);//发送QDynamicPropertyChangeEvent事件

        return false;//新增动态属性始终返回false
    }
    //静态属性直接修改其值
    QMetaProperty p = meta->property(id);
    return p.write(this, value);
}

QList dynamicPropertyNames() const

返回所有使用setProperty动态新增的属性名称列表

int senderSignalIndex()

返回调用当前执行槽的信号的元方法索引,它是sender()返回的类的成员。
应该在槽函数中调用,如果在由信号激活的槽之外调用,则返回-1。
对于带有默认参数的信号,此函数将始终返回带有所有参数的索引,而不管connect()使用了哪个参数。
例如,被销毁的信号(QObject *obj = nullptr)将有两个不同的索引(带参数和不带参数),但这个函数将始终返回带参数的索引。
这不适用于重载具有不同参数的信号。
警告:这个函数违反了面向对象的模块化原则。但是,当许多信号连接到单个槽时,访问信号索引可能很有用。
警告:当通过Qt::DirectConnection从不同于此对象线程的线程调用槽时,此函数的返回值无效。不要在这种场景中使用此函数。
这个函数是在Qt 4.8中引入的。

int receivers(const char* signal) const

返回连接到该信号的接收器的数量。
由于插槽和信号都可以用作信号的接收器,并且可以多次进行相同的连接,因此接收器的数量与从该信号进行连接的数量相同。

if (receivers(SIGNAL(valueChanged(QByteArray))) > 0) {
QByteArray data;
get_the_value(&data); // expensive operation
emit valueChanged(data);
}

bool inherits(const char *classname)

返回是否直接或间接继承了className类,是则返回true;否则返回false。
一个类被认为继承了它自己。
QTimer *timer = new QTimer; // QTimer inherits QObject
timer->inherits(“QTimer”); // returns true
timer->inherits(“QObject”); // returns true
timer->inherits(“QAbstractButton”); // returns false

// QVBoxLayout:public QObject ,public QLayoutItem{};
QVBoxLayout *layout = new QVBoxLayout;
layout->inherits(“QObject”); // returns true
layout->inherits(“QLayoutItem”); // returns true (even though QLayoutItem is not a QObject)

bool isSignalConnected(const QMetaMethod &signal)

如果信号连接到至少一个接收器,则返回true,否则返回false
Signal必须是该对象的信号成员,否则行为未定义。
static const QMetaMethod valueChangedSignal = QMetaMethod::fromSignal(&MyObject::valueChanged);
if (isSignalConnected(valueChangedSignal)) {
QByteArray data;
data = get_the_value(); // expensive operation
emit valueChanged(data);
}

void deleteLater()

计划删除此对象,当控制返回到事件循环时,对象将被删除
如果在调用此函数时事件循环没有运行(例如,在QCoreApplication::exec()之前在对象上调用deleteLater()),则一旦事件循环启动,该对象将被删除。
如果在主事件循环停止后调用deleteLater(),则不会删除对象。
自Qt 4.8以来,如果deleteLater()在没有运行事件循环的线程中的对象上调用,则该对象将在线程结束时被销毁。
注意,进入和离开一个新的事件循环(例如,通过打开一个模态对话框)不会执行延迟删除;对于要删除的对象,控件必须返回到从中调用deleteLater()的事件循环。
注意:多次调用这个函数是安全的;当交付第一个延迟删除事件时,对象的任何挂起事件都将从事件队列中删除。


void QObject::deleteLater()
{
    QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}


bool QObject::event(QEvent *e)
{
   case QEvent::DeferredDelete:
        qDeleteInEventHandler(this);
        break; 
}

void qDeleteInEventHandler(QObject *o)
{
    delete o;
}

static uint registerUserData()

注册用户数据类型,返回此类型id号

static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);

uint QObject::registerUserData()
{
    return user_data_registration.fetchAndAddRelaxed(1);
}

void setUserData(uint id, QObjectUserData* data)

设置对应id的用户数据类型的数据,数据必须是指针且不需要自己手动释放

void QObject::setUserData(uint id, QObjectUserData* data)
{
    Q_D(QObject);
    if (!d->extraData)
        d->extraData = new QObjectPrivate::ExtraData;

    if (d->extraData->userData.size() <= (int) id)
        d->extraData->userData.resize((int) id + 1);
    d->extraData->userData[id] = data;//用户数据是一个数组,里面保存不同类型的用户数据
}

QObjectUserData* userData(uint id) const

获取用户数据

QObjectUserData* QObject::userData(uint id) const
{
    Q_D(const QObject);
    if (!d->extraData)
        return nullptr;
    if ((int)id < d->extraData->userData.size())
        return d->extraData->userData.at(id);
    return nullptr;
}

userData自动析构

对象析构时自动析构释放所有用户数据

QObjectPrivate::~QObjectPrivate()
{
    if (extraData)
        qDeleteAll(extraData->userData);
    delete extraData;
}

template <typename Container>
inline void qDeleteAll(const Container &c)
{
    qDeleteAll(c.begin(), c.end());
}

void qDeleteAll(ForwardIterator begin, ForwardIterator end)
{
    while (begin != end) {
        delete *begin;//删除所有用户数据,对于用户数据里面含有指针的类型,有数据本身析构释放
        ++begin;
    }
}
ainer &c)
{
    qDeleteAll(c.begin(), c.end());
}

void qDeleteAll(ForwardIterator begin, ForwardIterator end)
{
    while (begin != end) {
        delete *begin;//删除所有用户数据,对于用户数据里面含有指针的类型,有数据本身析构释放
        ++begin;
    }
}
文章来源:https://blog.csdn.net/sinat_33263516/article/details/135540075
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。