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

问题描述 投票:15回答:5

或其他方式来表达我的问题(虽然它没有解决我的问题):'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的信号和插槽?

我很高兴有任何建议。

c++ qt qt-signals qobject slot
5个回答
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);
}

7
投票

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

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


2
投票

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

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


2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.