精华内容
下载资源
问答
  • QObject

    2020-08-14 20:31:43
    QT源码分析:QObject QObject 源代码阅读
    展开全文
  • paip 'QObject QObject const QObject ' is private问题的解决
                    paip. 'QObject::QObject(const QObject&)' is private问题的解决.
     
     作者Attilax ,  EMAIL:1466519819@qq.com 
    来源:attilax的专栏
    地址:http://blog.csdn.net/attilax




    详细:
    /
       D:\Qt\Qt5.1.1\5.1.1\mingw48_32\include\QtCore\qobject.h:426: 
              error: 'QObject::QObject(const QObject&)' is private
         Q_DISABLE_COPY(QObject)
              


         
    QObject QObject(const QObject&)  is private


    解决:
    /
     AtiMov  mv=    AtiMov();
     >>>>>>>>>>
      AtiMov* mv= new  AtiMov();
      
      
      参考:
      C++用new来创建对象和非new来创建对象的区别 - GOD_YCA - 博客园.htm           

    再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

    展开全文
  • QObject学习

    2021-05-27 11:22:25
    做一下QObject的相关笔记,准备来一个系统性的学习。 以下内容全部是个人理解,有谬误的地方欢迎大佬指出! QObject的成员变量 首先,我们先看一下QObject的大小: qDebug()<<sizeof(QObject); 结果...

     

    做一下QObject的相关笔记,准备来一个系统性的学习。

    以下内容全部是个人理解,有谬误的地方欢迎大佬指出!

    QObject的成员变量

    首先,我们先看一下QObject的大小:

        qDebug()<<sizeof(QObject);

    结果输出为8,我们打开QObject的源码,可以发现这8个字节是类的虚表指针和一个指针成员变量

    QScopedPointer<QObjectData> d_ptr;

    点开定义发现QScopedPointer是一个模板类,内部只有一个T*的指针,所以这个d_ptr其实就是一个QObjectData的指针,定义如下:

    class Q_CORE_EXPORT QObjectData {
    public:
        virtual ~QObjectData() = 0;
        QObject *q_ptr;
        QObject *parent;
        QObjectList children;
    
        uint isWidget : 1;
        uint blockSig : 1;
        uint wasDeleted : 1;
        uint isDeletingChildren : 1;
        uint sendChildEvents : 1;
        uint receiveChildEvents : 1;
        uint isWindow : 1; //for QWindow
        uint unused : 25;
        int postedEvents;
        QDynamicMetaObjectData *metaObject;
        QMetaObject *dynamicMetaObject() const;
    };

    这里面储存了QObject的一些信息,包括父节点指针,子节点指针,是否为Widget等。

    这样,QObject中包含了所有的方法,QObjectDate里存储数据信息,这就是QT的句柄实例设计模式,QObject是句柄类,QObjectDate则是实例类。所以,QObject的派生类可以说有两个基类,一个是QObject,另一个是QObjectDate。由此展开了d_ptr和p_ptr,这个以后在复习d指针的时候再展开。

    这样设计有什么好处,具体可以参考Pimpl机制,可以隐藏信息,降低耦合。

    接下来,我们看构造函数:

    QObject::QObject(QObject *parent)
        : d_ptr(new QObjectPrivate)
    {
        Q_D(QObject);
        d_ptr->q_ptr = this;
        d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
        d->threadData->ref();
        if (parent) {
            QT_TRY {
                if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
                    parent = 0;
                setParent(parent);
            } QT_CATCH(...) {
                d->threadData->deref();
                QT_RETHROW;
            }
        }
    #if QT_VERSION < 0x60000
        qt_addObject(this);
    #endif
        if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
            reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
    }

    我们注意到,调用构造函数的时候,我们new了一个QObjectPrivate给d_ptr赋值,翻看源码可以发现,QObjectPrivate继承了QObjectDate,并且提供了一些线程以及信号槽相关的具体实现,其实,所有的QObject的派生类都会在构造函数中new一个相应的private类,比如QPushButton:

    QPushButton::QPushButton(QWidget *parent)
        : QAbstractButton(*new QPushButtonPrivate, parent)
    {
        Q_D(QPushButton);
        d->init();
    }
    

    这个QpushButtonPrivate的继承关系里就有一环继承了QObjectPrivate。这里面的Q_D展开来就是QPushButtonPrivate* const d = d_func。

    至于QObjectPrivate如何进行信号槽的实现,留到以后再记录。

    对了,值得一提的是,QObject禁用了赋值和拷贝构造函数,因为QObject有唯一的名字,而且处于树型结构中,如果可以复制,无疑会增添很多麻烦,更不用说如何处理这些已经连接上的信号槽。

    继续说回QObject的构造函数。

    Q_D(QObject)的作用可以参考下面的宏的解释,其中变量d的类型为QObjectPrivate*,我们初始化了线程threadDate。

    QObject的宏定义

    1,Q_OBJECT

        以后分析元对象系统的时候再梳理

    2,Q_PROPERTY

        QT属性,留待以后分析

    3,Q_DECLARE_PRIVATE

    #define Q_DECLARE_PRIVATE(Class) \
        inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
        inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \
        friend class Class##Private;

    在这个宏中,创建了两个内联函数,将d_ptr转换成ClassPrivate*返回,帮我们获取指向实例的指针,而且还声明了友元类,可以让我们省去了访问权限的问题。值得一提的是,同名同参的函数如果返回值的const属性不同,也可以实现重载。

    4,Q_DECLARE_PUBLIC

    #define Q_DECLARE_PUBLIC(Class)                                    \
        inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
        inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
        friend class Class;

    同上面的宏类似,帮我们获取指向句柄的指针,在QObjectPrivate中使用。

    5,Q_D

    #define Q_D(Class) Class##Private * const d = d_func()

    定义了一个变量d指向了实例指针

    6,Q_Q

    #define Q_Q(Class) Class * const q = q_func()

    定义了变量q指向了句柄指针

     

    QObject的接口

    1, QThread *thread() const;

         返回对象所在的线程。

     

    2,void moveToThread(QThread *thread);

        if (d->threadData->thread == targetThread) {
            // object is already in this thread
            return;
        }

    这个很好理解,如果自身线程和目标线程相同,就什么都不做

        if (d->parent != 0) {
            qWarning("QObject::moveToThread: Cannot move objects with a parent");
            return;
        }

    被move的对象不能有父对象,不然无法move成功。

        if (d->isWidget) {
            qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
            return;
        }
    
        if (d->isWidget) {
            qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
            return;
        }
    

    QWidget只能在主线程。

        QThreadData *currentData = QThreadData::current();
        QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : Q_NULLPTR;
        if (d->threadData->thread == 0 && currentData == targetData) {
            // one exception to the rule: we allow moving objects with no thread affinity to the current thread
            currentData = d->threadData;
        } else if (d->threadData != currentData) {
            qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
                     "Cannot move to target thread (%p)\n",
                     currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR);
    
            return;
        }
    

    如果当前线程不是对象所在的线程,那么我们也无法将对象移动到目标线程,除非对象与当前线程没有关联。

       // prepare to move
        d->moveToThread_helper();
    
        if (!targetData)
            targetData = new QThreadData(0);
    
        QOrderedMutexLocker locker(&currentData->postEventList.mutex,
                                   &targetData->postEventList.mutex);
    
        // keep currentData alive (since we've got it locked)
        currentData->ref();
    
        // move the object
        d_func()->setThreadData_helper(currentData, targetData);
    
        locker.unlock();
    
        // now currentData can commit suicide if it wants to
        currentData->deref();

    然后我们将对象移动到了目标线程。

     

    3, static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,const QObject *receiver, const QMetaMethod &method,Qt::ConnectionType type = Qt::AutoConnection);

        if (sender == 0
                || receiver == 0
                || signal.methodType() != QMetaMethod::Signal
                || method.methodType() == QMetaMethod::Constructor) {
            qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
                     sender ? sender->metaObject()->className() : "(null)",
                     signal.methodSignature().constData(),
                     receiver ? receiver->metaObject()->className() : "(null)",
                     method.methodSignature().constData() );
            return QMetaObject::Connection(0);
        }

    信号的发送者和接收者都不能为空,而且第二个参数signal的类型必须为Signal,第四个参数method不能为构造函数,不然直接返回。

        int signal_index;
        int method_index;
        {
            int dummy;
            QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
            QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
        }
    
        const QMetaObject *smeta = sender->metaObject();
        const QMetaObject *rmeta = receiver->metaObject();
        if (signal_index == -1) {
            qWarning("QObject::connect: Can't find signal %s on instance of class %s",
                     signal.methodSignature().constData(), smeta->className());
            return QMetaObject::Connection(0);
        }
        if (method_index == -1) {
            qWarning("QObject::connect: Can't find method %s on instance of class %s",
                     method.methodSignature().constData(), rmeta->className());
            return QMetaObject::Connection(0);
        }
    
        if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
            qWarning("QObject::connect: Incompatible sender/receiver arguments"
                     "\n        %s::%s --> %s::%s",
                     smeta->className(), signal.methodSignature().constData(),
                     rmeta->className(), method.methodSignature().constData());
            return QMetaObject::Connection(0);
        }

    检查当作参数的信号和槽函数是否真实存在,如果不存在也返回空。

        if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
            qWarning("QObject::connect: Incompatible sender/receiver arguments"
                     "\n        %s::%s --> %s::%s",
                     smeta->className(), signal.methodSignature().constData(),
                     rmeta->className(), method.methodSignature().constData());
            return QMetaObject::Connection(0);
        }

    检查信号的形参是否一致。

        int *types = 0;
        if ((type == Qt::QueuedConnection)
                && !(types = queuedConnectionTypes(signal.parameterTypes())))
            return QMetaObject::Connection(0);

    如果采用多线程的枚举来连接,要检查参数是否为元数据,如果是自定义的数据,那么必须调用qRegisterMetaType进行注册,不然会连接失败。另外,如果参数是引用类型,也无法跨线程连接。

    #ifndef QT_NO_DEBUG
        check_and_warn_compat(smeta, signal, rmeta, method);
    #endif
        QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
            sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, 0, type, types));
        return handle;

    连接成功。另外,对于重载的情况,我们可以使用QOverload<T>::of来进行转化,达到信号和曹的匹配。

     

    4,bool blockSignals(bool b) Q_DECL_NOTHROW;

    源码很简单,没啥好说的,作用是,当b为真的时候,阻塞信号的发出,为假的时候,取消阻塞。

     

    5,int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);

    这个接口用来启动一个定时器事件,并返回定时器id,如果失败就返回0。定时器每隔interval 毫秒就会启动一次,直到调用killTimer()。当定时器发生时,会调用timerEvent(QTimerEvent *event).如果多个定时器在运行,可用通过定时器id来区分。

        if (Q_UNLIKELY(interval < 0)) {
            qWarning("QObject::startTimer: Timers cannot have negative intervals");
            return 0;
        }

    时间不能为负数。

        if (Q_UNLIKELY(!d->threadData->eventDispatcher.load())) {
            qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
            return 0;
        }

    这也是经常能碰到的情况。可以通过连接 QThread :: started信号 触发的槽函数启动定时器来解决。

     

        if (Q_UNLIKELY(thread() != QThread::currentThread())) {
            qWarning("QObject::startTimer: Timers cannot be started from another thread");
            return 0;
        }

    定时器所处的线程要和当前调用的线程相同才行

        int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
        if (!d->extraData)
            d->extraData = new QObjectPrivate::ExtraData;
        d->extraData->runningTimers.append(timerId);
        return timerId;

    接下来就启动成功,返回相应的定时器id。

     

    6, void killTimer(int id);

      用法就是停止对应的定时器。

        Q_D(QObject);
        if (Q_UNLIKELY(thread() != QThread::currentThread())) {
            qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
            return;
        }

    也是经常能遇到的问题,我们定时器对象所处的线程必须和当前调用函数的线程相同。

        if (id) {
            int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
            if (at == -1) {
                // timer isn't owned by this object
                qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %s), timer has not been killed",
                         id,
                         this,
                         metaObject()->className(),
                         qPrintable(objectName()));
                return;
            }

    这个定时器id必须由这个对象产生的才能调用。

            if (d->threadData->eventDispatcher.load())
                d->threadData->eventDispatcher.load()->unregisterTimer(id);
    
            d->extraData->runningTimers.remove(at);
            QAbstractEventDispatcherPrivate::releaseTimerId(id);

    开始定时器就是d->extraData->runningTimers加入时间id,结束就是remove掉。

     

     

     

     

                                                      (这个图太久了,忘记在哪里看到了,直接用了,如果侵犯了您的权益请私信本人删除)

    展开全文
  • QObject 详解

    2021-03-16 10:04:23
    QObject描述 1、QObject类是所有Qt对象的基类。 2、QObject是Qt对象模型的核心。该模型的核心特性是一种非常强大的无缝对象通信机制,称为信号和槽。可以使用connect()将信号连接到槽,并使用disconnect()销毁连接...

    QObject描述

    1、QObject类是所有Qt对象的基类。

    2、QObject是Qt对象模型的核心。该模型的核心特性是一种非常强大的无缝对象通信机制,称为信号和槽。可以使用connect()将信号连接到槽,并使用disconnect()销毁连接。为了避免永无止境的通知循环,可以使用blockSignals()临时阻止信号。受保护的函数connectNotify()和disconnectNotify()使跟踪连接成为可能。

    3、对象通过对象树的形式组织。当创建一个以另一个对象为父对象的QObject时,该对象将自动将自己添加到父对象的children()列表中。父对象拥有对象的所有权,父对象将在析构函数中自动删除它的子对象。可以使用findChild()或findChildren()查找对象的子对象。

    4、每个对象都有一个objectName(),其类名可以通过相应的metaObject()找到。可以使用inherits()函数确定对象的类是否继承QObject继承层次结构中的另一个类。

    5、当一个对象被删除时,它会发出一个destroyed()信号。

    6、QObjects可以通过event()接收事件并过滤其他对象的事件。可以重新实现方便的处理程序childEvent(),以捕获子事件。

    7、QObject在Qt中提供了基本的计时器支持。

    8、对于实现信号、插槽或属性的任何对象,Q_OBJECT宏都是必需的。还需要在源文件上运行元对象编译器。强烈建议在QObject的所有子类中使用此宏,不管它们是否实际使用信号、插槽和属性,否则可能会导致某些函数表现出奇怪的行为。

    9、所有Qt widgets都继承QObject。函数isWidgeType()返回一个对象是否是一个widget。它比qobject_cast<QWidget *>(obj)或obj->inherits(“QWidget”)快得多。

     

    线程相关

    1、当QObject接收到信号或发布的事件时,槽函数或事件处理程序将在对象所在的线程中运行。(如果QObject没有线程关联(即如果thread()返回nullptr),或者如果它位于没有运行事件循环的线程中,则它无法接收信号或发布的事件)。

    2、默认情况下,QObject存在于创建它的线程中。可以使用thread()查询对象的线程关联,并使用moveToThread()更改对象的线程关联。

    3、所有QObject必须与其父对象位于同一线程中。因此:如果所涉及的两个QObject位于不同的线程中,setParent()将失败。当一个QObject对象被移动到另一个线程时,该对象的所有子线程也将被自动移动。如果QObject对象有父对象,moveToThread()将失败。如果QObject对象是在QThread::run()中创建的,则它们不能成为QThread对象的子对象,因为QThread对象不在调用QThread::run()的线程中。注意:QObject的成员变量不会自动成为其子变量。必须通过向子构造函数传递指针或调用setParent()来设置父子关系。如果没有此步骤,调用moveToThread()时,对象的成员变量将保留在旧线程中。

    无复制构造函数和赋值运算符

    QObject既没有复制构造函数,也没有赋值运算符。它们是在宏Q_DISABLE_COPY()中设置了禁止生成。实际上,所有从QObject派生的Qt类(直接或间接)都使用这个宏来声明它们的复制构造函数和赋值操作符是私有的。

    这带来的结果是应该使用指向QObject(或者指向您的QObject子类)的指针。例如,如果没有复制构造函数,就不能使用QObject的子类作为存储在某个容器类中的值,必须存储指针。

    例:企图拷贝和赋值QWidget时会报错:

    图片

     

    图片

    函数=delete

    自动连接(ui文件)

    Qt的元对象系统提供了一种机制来自动连接QObject子类及其子类之间的信号和槽。只要用合适的对象名定义对象,并且槽遵循简单的命名约定,就可以在运行时通过QMetaObject::connectSlotsByName()函数执行此连接。

    uic生成调用此函数的代码,以便在使用Qt Designer创建的窗体上的小部件之间执行自动连接。

    例:ui文件拖入一个按钮,objectName设置为btn,则按钮发出clicked()信号时就会调用on_btn_clicked()槽函数(此函数必须声明为槽)。他们之间通过QMetaObject::connectSlotsByName()关联起来的。

    图片

    图片

    动态属性

    从Qt4.2开始,可以在运行时向QObject实例添加动态属性,也可以从QObject实例中删除动态属性。动态属性不需要在编译时声明,但是它们提供了与静态属性相同的优点,并且使用相同的API进行操作—使用property()读取它们,使用setProperty()写入它们。

    从qt4.3开始,Qt Designer支持动态属性,并且标准Qt小部件和用户创建的表单都可以被赋予动态属性。

    图片

    国际化(I18n)

    所有QObject子类都支持Qt的翻译特性,使得将应用程序的用户界面翻译成不同的语言成为可能。要使用户可见的文本可翻译,必须将其包装在对tr()函数的调用中。

    属性成员

    QObject只有一个属性:objectName,用来包含对象的名称,当要查找子对象时可以使用findChild()通过对象名称查找对象。默认此属性为空。

    成员函数

    1、QObject::QObject(QObject *parent = nullptr)构造函数

    将parent设置为nullptr将构造一个没有父对象的对象。如果对象是一个QWidget,它将成为一个顶级窗口。这个函数可以通过元对象系统和QML调用。

    2、[slot] void QObject::deleteLater()

    发起一个事件,当事件循环处理到该事件时删除当前对象,源码:

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

    如果调用此函数时事件循环未运行,则一旦启动事件循环,该对象将被删除。如果在主事件循环停止后调用deleteLater(),则不会删除该对象。从Qt4.8开始,如果对没有运行事件循环的线程中的对象调用deleteLater(),则该对象将在线程完成时被销毁。

    可参考:Qt deleteLater原理

    3、[signal] void QObject::destroyed(QObject *obj = nullptr)

    对象被删除之前发送此信号。

    4、[signal] void QObject::objectNameChanged(const QString &objectName)

    此信号在对象名称更改后发出。新对象名作为参数传递。注意:这是一个私有信号。它可以用于信号连接,但不能由用户发射。

    5、QObject::~QObject()析构函数

    销毁对象,删除其所有子对象。与对象关联的所有信号都将自动断开,并且对象的任何挂起的已发布事件都将从事件队列中删除。建议任何时候都不要直接delete一个QObject对象,应该用deleteLater()代替。

    6、bool QObject::blockSignals(bool block)

    如果block为true,则此对象发出的信号将被阻塞(即,发出信号将不会调用任何与之连接的槽对象)。如果block为false则取消阻塞。

    建议使用QSignalBlocker代替,更安全。信号阻塞器QSignalBlocker

    7、bool QObject::signalsBlocked() const

    如果当前对象处于信号被阻塞状态返回true,否则返回false。

    8、void QObject::childEvent(QChildEvent *event)

    子对象事件处理,子对象事件就这几种:

    图片

    例:

    void Widget::childEvent(QChildEvent *event)
    {
        QEvent::Type t = event->type();
        if(t == QEvent::ChildAdded)
        {
            if(QObject * child = event->child())
            {
                qDebug()<<"添加了子对象,对象名称:"<< child->objectName();
            }
        }
        else if(t == QEvent::ChildRemoved)
        {
            if(QObject * child = event->child())
            {
                qDebug()<<"移除了子对象,对象名称:"<< child->objectName();
            }
        }
    }
    
    void Widget::on_btn_clicked()
    {
        QPushButton * btn = new QPushButton("新增按钮");
        btn->setObjectName("newBtn");
        btn->setParent(this);
        btn->show();
        btn->setGeometry(10,10,100,50);
    }
    
    void Widget::on_btn_2_clicked()
    {
        if(QPushButton * btn = this->findChild<QPushButton *>("newBtn"))
        {
            btn->setParent(nullptr);
            btn->deleteLater();
        }
    }

    图片

    9、const QObjectList &QObject::children() const

    获取对象的子对象列表。QObjectList 是QList<QObject*>的别名(typedef QList<QObject*> QObjectList;)

    10、void QObject::connectNotify(const QMetaMethod &signal)

    当有信号连接当前对象时,调用此函数。

    图片

    貌似只有本身的信号连接本身的函数时才会调用,其他对象的信号连接本身的函数不会调用。disconnectNotify()功能与之相反。

    11、void QObject::customEvent(QEvent *event)

    处理自定义事件,见:QT事件:自定义事件

    12、void QObject::dumpObjectInfo() const        

    将信号的信息转存到调试输出。

    13、void QObject::dumpObjectTree() const

    将对象树信息转存到调试输出。

    14、QList<QByteArray> QObject::dynamicPropertyNames() const (实用)

    获取所有动态属性名。

    15、bool QObject::event(QEvent *e)

    事件处理,一般由子类重写。

    16、bool QObject::eventFilter(QObject *watched, QEvent *event)、QObject::installEventFilter(QObject *filterObj)、void QObject::removeEventFilter(QObject *obj)

    事件过滤器,监视注册过的对象,要过滤掉事件,即停止进一步处理,则返回true;否则返回false。

    MainWindow::MainWindow()
      {
          textEdit = new QTextEdit;
          textEdit->installEventFilter(this);
      }
    
      bool MainWindow::eventFilter(QObject *obj, QEvent *event)
      {
          if (obj == textEdit) {
              if (event->type() == QEvent::KeyPress) {
                  QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
                  qDebug() << "Ate key press" << keyEvent->key();
                  return true;
              } else {
                  return false;
              }
          } else {
              // pass the event on to the parent class
              return QMainWindow::eventFilter(obj, event);
          }
      }

    在上面的示例中,未处理的事件被传递给基类的eventFilter()函数,因为基类可能出于自身的内部目的重新实现了eventFilter()。

    某些事件,如QEvent::ShortcutOverride,必须被显式接受(通过对它们调用accept()),以防止传播。

    17、T QObject::findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

    查找单个子对象,参数1是objectName,参数2是标识是否递归查找(在对象的子对象中查找)。

    18、QList<T> QObject::findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

           QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

    查找满足条件的子对象,第二个版本的objectName与正则表达式匹配。

    19、bool QObject::inherits(const char *className) const

    获取某个类是否继承自另一个类。

    QTimer *timer = new QTimer;
      timer->inherits("QTimer");          // true
      timer->inherits("QObject");         // true

    20、bool QObject::isSignalConnected(const QMetaMethod &signal) const (实用)

    某信号是否至少有一个接收者。

    connect(this,&Widget::linked,this,&Widget::test);
        static const QMetaMethod linkedSignal = QMetaMethod::fromSignal(&Widget::linked);
        qDebug()<<isSignalConnected(linkedSignal);//true
        disconnect(this,&Widget::linked,this,&Widget::test);
        qDebug()<<isSignalConnected(linkedSignal);//false

    当需要仅在某些东西连接到信号时才执行昂贵代价的初始化时此函数很有用。

    21、bool QObject::isWidgetType() const

    是否是一个QWidget类型。(相当于调用:inherits("QWidget");)

    22、const QMetaObject *QObject::metaObject() const

    获取当前对象的元对象。

    元对象包含有关继承QObject的类的信息,例如类名、父类名、属性、信号和槽。每个包含Q_OBJECT宏的QObject子类都有一个元对象。

    信号/槽连接机制和属性系统需要元对象信息。inherits()函数也使用元对象。

    QObject *obj = new QPushButton;
      obj->metaObject()->className();             // returns "QPushButton"

    23、void QObject::moveToThread(QThread *targetThread)

    更改此对象及其子对象的线程关联。如果对象有父对象,则无法移动。事件处理将在targetThread中继续。

    要将对象移动到主线程,请使用QApplication::instance()检索指向当前应用程序的指针,然后使用QApplication::thread()检索应用程序所在的线程。例如:

     myObject->moveToThread(QApplication::instance()->thread());

    targetThread为nullptr,则此对象及其子对象的所有事件处理都将停止,因为它们不再与任何线程关联。

    targetThread如果不是nullptr,则发布到此对象的任何新事件都将在targetThread中处理;如果是nullptr,则不会对该对象或其子对象进行事件处理,因为它们不再与任何线程关联。

    对象的所有活动计时器都将重置。计时器首先在当前线程中停止,然后在targetThread中重新启动(间隔相同)。

    在更改线程关联之前,会向该对象发送QEvent::ThreadChange事件。

    24、QObject *QObject::parent() const

    获取父对象。

    25、QVariant QObject::property(const char *name) const

    获取属性,如果属性不存在,获取的QVariant是无效的。

    26、int QObject::receivers(const char *signal) const     (实用)

    获取一个信号有多少个接收者。(信号连接信号的情况也算)

    signals:
        void linked();
        void linked2();
    
        qDebug()<<receivers(SIGNAL(linked()));//0
        connect(this,&Widget::linked,this,&Widget::test);
        qDebug()<<receivers(SIGNAL(linked()));//1
        connect(this,&Widget::linked,this,&Widget::linked2);
        qDebug()<<receivers(SIGNAL(linked()));//2

    27、QObject *QObject::sender() const

    获取信号发送者。

    如果在由信号激活的槽函数中调用,则返回指向发送信号的对象的指针;否则返回nullptr。

    当从与此对象线程不同的线程通过Qt::DirectConnection调用插槽时,此函数的返回值无效。不要在这种情况下使用此函数。

    28、int QObject::senderSignalIndex() const

    获取信号在元对象中方法的索引。

    29、void QObject::setParent(QObject *parent)

    设置父对象。

    30、bool QObject::setProperty(const char *name, const QVariant &value)

    设置属性。如果该属性已经在类中使用Q_PROPERTY定义,则在成功时返回true,否则返回false。如果该属性没有使用Q_PROPERTY定义,因此没有列在元对象中,则将其添加为动态属性并返回false。有关所有可用属性的信息都是通过metaObject()和dynamicPropertyNames()提供的。可以使用property()查询动态属性,并且可以通过将属性值设置为无效的QVariant来删除动态属性。更改动态属性的值会将QDynamicPropertyChangeEvent发送到对象。

    注意:以“_q_开头的动态属性保留于内部使用。

    31、QThread *QObject::thread() const

    获取对象所在线程。

    32、QString QObject::tr(const char *sourceText, const char *disambiguation = nullptr, int n = -1)

    获取字符串的翻译文本,若是没有合适的文本则返回QString::fromUtf8(sourceText),参数2是标识字符串,用作:如果上下文有两个一样的源字符串但在翻译里表示不同的意思,则可以用标识字符串消除歧义。

    成员变量

    const QMetaObject QObject::staticMetaObject

    静态元对象。

    QPushButton::staticMetaObject.className();  // returns "QPushButton"

    相关非成员

    T qobject_cast(const QObject *object)

    如果给定的对象属于T类型(或子类),则返回转换为T类型的对象;否则返回nullptr。如果对象是nullptr,那么它也将返回nullptr。

    类T必须继承(直接或间接)QObject并用Q_OBJECT宏声明。

    类被认为是继承自身的。

     1、QT_NO_NARROWING_CONVERSIONS_IN_CONNECT

    信号槽参数禁止窄化转换。

    比如信号参数为double类型,对应的槽函数类型为int,信号槽关联后运行起来是没问题的,在槽函数中处理时double类型的值会窄化转成int类型的值,在pro文件中加入此宏:

    DEFINES += QT_NO_NARROWING_CONVERSIONS_IN_CONNECT

    编译就会报错。

    2、Q_CLASSINFO(实用)

    给类设置额外信息。

    图片

    QMetaClassInfo info = this->staticMetaObject.classInfo(0);
        qDebug()<<info.name() <<" : "<<info.value();
        info = this->staticMetaObject.classInfo(1);
        qDebug()<<info.name() <<" : "<<info.value();

    图片

    3、Q_DISABLE_COPY(Class)

    禁止拷贝和赋值。

    4、Q_DISABLE_MOVE(Class)

    禁止移动构造及移动赋值。

    5、Q_DISABLE_COPY_MOVE(Class)

    禁止拷贝和移动。

     6、Q_EMIT、Q_SIGNAL、Q_SLOT

    Q_EMIT的效果和emit一样。一些第三方库如boost会使用emit作为关键字。如果使用了这些第三方库则使用此宏代替emit。Q_SIGNAL、Q_SLOT、Q_SIGNALS、Q_SLOTS类似。

    7、Q_ENUM

    向元对象系统注册枚举,必须放在Q_OBJECT和Q_GADGET的声明后面。

    enum class Priority { High, Low, VeryHigh, VeryLow };
        Q_ENUM(Priority)
    qDebug()<< Widget::Priority::High<< Widget::Priority::Low;
        QMetaEnum m = QMetaEnum::fromType<Widget::Priority>();
        qDebug()<< "key To Value:"<< m.keyToValue("VeryHigh");
        qDebug()<< "value To Key:"<< m.valueToKey(static_cast<int>(Widget::Priority::VeryHigh));
        qDebug()<< "key Count:"<< m.keyCount();

    图片

    注册过后的枚举可以用qDebug直接打印出来,key和value互转也很方便。

    8、Q_FLAG、Q_NAMESPACE、Q_ENUM_NS、Q_FLAG_NS

    见:QFlags详解

    9、Q_GADGET

    对于不继承QObject但仍希望使用QMetaObject提供的某些反射功能的类(仅仅使用反射功能,无需继承自QObject),Q_GADGET宏是Q_OBJECT宏的轻量级版本。与Q_OBJECT宏一样,它必须出现在类定义的私有部分中。

    Q_GADGET可以具有Q_ENUM、Q_PROPERTY和Q_INVOKABLE,但它们不能有信号或槽。

    Q_GADGET使类成员staticMetaObject可用。staticMetaObject类型为QMetaObject。

    10、Q_INTERFACES

    这个宏告诉Qt类实现了哪些接口。实现插件时使用的。如:

    class BasicToolsPlugin : public QObject,
                               public BrushInterface,
                               public ShapeInterface,
                               public FilterInterface
      {
          Q_OBJECT
          Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json")
          Q_INTERFACES(BrushInterface ShapeInterface FilterInterface)
      public:
          ...
      };

     插件实现了 BrushInterface、ShapeInterface、FilterInterface这3个接口。

    11、Q_INVOKABLE

    将此宏应用于成员函数的声明,以允许通过元对象系统调用它们。宏写在返回类型之前,如:

    12、Q_OBJECT

    Q_OBJECT宏必须出现在类定义的private部分,使用此宏可以声明自己的信号和槽、使用Qt的元对象系统。这个宏要求类是QObject的子类。

    13、Q_PROPERTY

    此宏用于在继承QObject的类中声明属性。

    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])

     属性名和类型以及READ函数是必需的。类型可以是QVariant支持的任何类型,也可以是用户定义的类型。其他项是可选的,但WRITE函数是常见的。属性默认为true,但USER默认为false。例:

    Q_PROPERTY(QString title READ title WRITE setTitle USER true)

    14、Q_REVISION

    设置槽函数和属性在元对象系统中的修订版本。

    图片

    打印修订版本大于1的属性和方法:

    int main(int argc, char *argv[])
    {
        QApplication a(argc,argv);
        Widget w;
        w.show();
        int expectedRevision = 1;
        const QMetaObject *windowMetaObject = w.metaObject();
    
        for (int i=0; i < windowMetaObject->methodCount(); i++)
            if (windowMetaObject->method(i).revision() > expectedRevision)
                debug windowMetaObject->method(i).name();
    
        for (int i=0; i < windowMetaObject->propertyCount(); i++)
            if (windowMetaObject->property(i).revision() > expectedRevision)
                debug windowMetaObject->property(i).name();
    
        a.exec();
    }

    图片

    15、Q_SET_OBJECT_NAME    (实用,可以便捷设置objectName)

    把一个对象变量名(指针变量也可以)设为对象的objectName。(QObject及其子类才有用)

    Widget w666;
        Q_SET_OBJECT_NAME(w666);
        w666.show();
        debug w666.objectName();//w666

     

    参考

    1. QObject 详解
    展开全文
  • QObject.xmind

    2020-02-12 13:56:10
    内容:以思维导图的方式详细介绍了“QObject”的概念以及功能 软件:xmind 问题:有问题多交流
  • QObject class

    2019-03-18 22:55:08
    The QObject class is the base class of all Qt objects. QObject is the heart of the Qt Object Model. The central feature in this model is a very powerful mechanism for seamless object communication ca...
  • QObject源码分析

    2021-03-03 18:47:23
    QObject是Qt的基类 QObject object; qDebug() << sizeof (object); QObject的大小是8,除了虚函数表指针需要的4个字节以外,另外的4个字节是QScopedPointer d_ptr; QObjectData QObjectData中存储了Qt对象的...
  • Qt:QObject

    2021-04-08 20:42:58
    QObject类是所有Qt对象的基类。 头文件: #include <QObject> cmake: find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) qmake: QT += core 注意:此类...
  • Qt--QObject

    千次阅读 2017-11-22 12:12:39
    QObject上一节中我们讲了QObject是Qt中使用Meta-Object元对象模型或者说使用信号与槽机制,必须继承的根基类,一般面向对象语言都会有这么一个根基类,提供了语言的基础,那么Qt作为C++的扩展库,QObject作为Qt的根...
  • QObject的Timer

    2021-03-26 16:46:53
    int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer) 开启一个时钟,周期是interval,开启成功返回时钟ID,开启失败返回0 void QObject::killTimer(int id) 关闭一个时钟 ...
  • QObject详解

    千次阅读 2018-04-16 13:09:22
    QObject类是所以Qt类的基类,也是Qt对象模型的核心。这个模型中的核心特性就是能让对象键无缝通信的信号和槽的机制。我们可以使用connect()函数将一个信号连接到一个槽上,也可以使用disconnect()删除这个连接。为了...
  • /opt/QtEmbedded-4.7.3/include/QtCore/qobject.h:309: error: ‘QObject&amp; QObject::operator=(const QObject&amp;)’ is private /opt/QZXing/QZXing.h:28: error: within this context 弄了一会才明白...
  • QObject.h

    2018-09-07 21:09:03
    #ifndef QOBJECT_H #define QOBJECT_H 2, 条件编译 #ifndef QT_NO_QOBJECT #endif 3, 前置声明类,用于类指针或引用的声明 class QEvent; class QTimerEvent; 4, typedef 别名 typedef QList&lt;...
  • 1.qobject_cast 最近在看一份开源项目时看到有qobject_cast的用法,经查阅学习后,记录文档 部分资料来自 安全的转换方式——qobject_cast 2.用法 函数原型: T qobject_cast ( QObject * object ) 本方法返回object向...
  • QT 利用继承Qobject实现多线程 利用moveToThread()函数将所需在新线程中处理的内容转移到开辟的新线程中 此外还利用了对不同线程进行加锁
  • 【Qt】QObject详解

    2021-03-27 22:02:34
    QObject类是所以Qt类的基类,也是Qt对象模型的核心。这个模型中的核心特性就是能让对象键无缝通信的信号和槽的机制。我们可以使用connect()函数将一个信号连接到一个槽上,也可以使用disconnect()删除这个连接。为了...
  • 关于 QObject

    2019-03-04 16:02:00
    1.QObject类 简述 QObject类是所有Qt对象的基类。 QObject是Qt对象模型的核心。该模型的核心特征是称为信号和槽的对象通信机制。您可以使用connect()将信号连接到槽,并用disconnect()终止该连接。为了...
  • 实现QObject与JavaScript通讯(基于QWebEngine + QWebChannel)
  • QT源码分析QObject

    2019-09-25 19:38:57
    简介: QT源码分析QObject,由此管中窥豹 文章目录QT源码分析:QObject:1.宏Q_OBJECT:2.宏Q_PROPERTY:3.宏Q_DECLARE_PRIVATE:4.构造函数:5.moveToThread:6.connect函数: QT源码分析:QObject: QT框架里面最大...
  • Qt:QObject浅析

    2021-01-09 14:52:08
    QObject类是Qt对象模型的核心类,也是所有Qt所有类对象的基类。继承QObject,我们可以使用其相应的功能,包括熟悉的信号与槽机制,接收事件,一些计时器,翻译等。 所有QObject会被记录在一个全局的对象树中,当以...
  • QObject类详述

    2018-06-23 23:14:32
    QObject类详述QObject类从Qt类继承,是所有Qt对象的基类,Qt类含有全局需要的各种枚举类型、类型的定义。通常情况下,用户不需要关心这个类,因为它是QObject及很少几个类的基类。例如:它定义了枚举类型ButtonState...
  • QObject

    千次阅读 2013-09-05 10:27:05
    来自:这个文件是Qt工具包一部分。 版权所有 © 1995-2002 Trolltech。 ...QObject类是所有Qt对象的基类。 详情请见…… #include qobject.h> 继承了Qt。 被QAccel、QAccessibleObject

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,923
精华内容 14,769
关键字:

qobject