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

时间:2011-09-21 15:38:10

标签: c++ qt qt-signals qobject slot

或以其他方式提出我的问题(虽然它没有解决我的问题):'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 个答案:

答案 0 :(得分:11)

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

您可以从Handler派生一个类QObject,其中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);
}

答案 1 :(得分:7)

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

否则,不,你不可能在不从QObject派生的情况下做你想要的事情,因为那个基类是处理Qt运行时信号/插槽功能的。

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

在Qt5中,您使用QObject::connectsignalslot联系起来:

/*
   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