首页 文章

如何在不派生QObject的情况下使用SIGNAL和SLOT?

提问于
浏览
15

或其他方式来表达我的问题(虽然它没有解决我的问题):'QObject::QObject' cannot access private member declared in class 'QObject'

我的课程中需要SIGNALs和SLOTS功能,但我认为不可能从 QObject 派生出来?

class MyClass
{
signals:
   importantSignal();
public slots:
   importantSlot();
};

问题似乎是我需要从 QObject 派生出来使用信号和插槽......但我需要 MyClass 的默认构造函数 . 但由于 QObject 的以下特征,我无法构造它们:No Copy Constructor or Assignment Operator .

我试了很多......

所以我的上课看起来像这样:

#include <QObject>
class MyClass: public QObject
{
    Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0); //autogenerated by qtcreator for QObject derived class
    MyClass(const MyClass * other);

signals:
    importantSignal();
public slots:
    importantSlot();
};

我需要 MyClass 的默认构造函数 .

那么有没有可能避免“'QObject :: QObject'无法访问类'QObject'中声明的私有成员”错误?

或者作为替代方案是否有可能使用信号和插槽而没有 QObject

我很高兴有任何建议 .

5 回答

  • 1

    如果您想要一个具有 QObject 功能的可复制对象,则需要成员资格(通过指针)而不是继承 .

    您可以从 QObject 派生一个类 Handler ,其中 Handler 的插槽在其父级上调用 SomeInterface 虚函数 .

    struct NonQObjectHandler {
        virtual ~ NonQObjectHandler () {}
        virtual void receive (int, float) = 0;
    };
    
    class Handler : public NonQObjectHandler {
        struct Receiver;
        std :: unique_ptr <Receiver> m_receiver;
        void receive (int, float); // NonQObjectHandler
    public:
        Handler ();
        Handler (const Handler &); // This is what you're really after
    };
    
    class Handler :: Receiver : public QObject {
    Q_OBJECT
    private:
        NonQObjectHandler * m_handler;
    private slots:
        void receive (int, float); // Calls m_handler's receive
    public:
        Receiver (NonQObjectHandler *);
    };
    
    Handler :: Handler ()
    : m_receiver (new Receiver (this))
    {
    }
    
    Handler :: Handler (const Handler & old)
    : m_receiver (new Receiver (this))
    {
        // Copy over any extra state variables also, but
        // Receiver is created anew.
    }
    
    Handler :: Receiver :: Receiver (NonQObjectHandler * h)
    : m_handler (h)
    {
        connect (foo, SIGNAL (bar (int, float)), this, SLOT (receive (int, float)));
    }
    
    void Handler :: Receiver :: receive (int i, float f)
    {
        m_handler -> receive (i, f);
    }
    
  • 11

    如果你想使用信号/槽模式实现事件驱动的功能,但又不想在Qt的范围内工作(即,你想在STL容器内使用你的类,需要复制构造函数等),我建议使用Boost::signal .

    否则,不,你可以't possibly do what you'想要而不从 QObject 派生,因为那个基类是处理Qt运行时信号/槽功能的 .

  • 7

    如果不使用 QObject / Q_OBJECT ,则无法使用Qt的信号/插槽机制 .

    理论上,您可以创建一个虚拟QObject并将其组合到您的类中 . 然后,假人会将插槽调用转发给您的 class . 由于Liz在评论中描述的原因,您可能会遇到终身管理问题 .

  • 2

    从Qt5开始,您可以连接到任何功能

    connect(&timer, &QTimer::finished,
            &instanceOfMyClass, &MyClass::fancyMemberFunction);
    
  • 2

    在Qt5中,您使用 QObject::connect 连接 signalslot

    /*
       QMetaObject::Connection QObject::connect(
        const QObject *sender,
        const char *signal,
        const char *method,
        Qt::ConnectionType type = Qt::AutoConnection) const;
     */
    
    #include <QApplication>
    #include <QDebug>
    #include <QLineEdit>
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        QLineEdit lnedit;
    
        // connect signal `QLineEdit::textChanged` with slot `lambda function`
        QObject::connect(&lnedit, &QLineEdit::textChanged, [&](){qDebug()<<lnedit.text()<<endl;});
    
        lnedit.show();
        return app.exec();
    }
    

    结果:

    enter image description here

相关问题