Как использовать SIGNAL и SLOT без вывода QObject?

ИЛИ другой способ сформулировать мой вопрос (хотя это не решило мою проблему): "QObject:: QObject" не может получить доступ к закрытому члену, объявленному в классе QObject

Мне нужны функции SIGNALs и SLOTS в моем классе, но я предполагаю, что это невозможно без вывода из QObject?

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

Кажется, что проблема состоит в том, что для использования сигналов и слотов мне нужно извлечь из QObject... но мне нужен конструктор по умолчанию MyClass. Но я не могу их построить из-за следующей функции QObject: Нет конструктора копирования или оператора присваивания.

Я много пробовал...

Итак, мой класс shoul выглядит так:

#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?

Я рад за любой совет.

Ответы

Ответ 1

Если вам нужен объект для копирования с 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 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);
}

Ответ 2

Если вы хотите реализовать управляемые событиями функции с использованием шаблона сигналов/слотов, но не хотите работать внутри границ Qt (т.е. вы хотите использовать свой класс внутри контейнеров STL и т.д., которые требуют копирования, конструкторы), я бы предложил использовать Boost:: signal.

В противном случае нет, вы не можете делать то, что хотите, не получая от QObject, поскольку этот базовый класс - это то, что обрабатывает функциональные возможности Qt runtime signal/slots.

Ответ 3

Вы не можете использовать механизмы сигнала/слота Qt, не используя QObject/Q_OBJECT.

Теоретически вы можете создать фиктивный QObject и скомпоновать его в свой класс. Затем манекен перенаправляет вызовы слотов в ваш класс. Вероятно, вы столкнетесь с проблемами управления жизненным циклом по причинам, которые Лиз описала в своем комментарии.

Ответ 4

Так как Qt5 вы можете просто подключиться к любой функции

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

Ответ 5

В Qt5 вы используете QObject::connect для подключения signal к slot:

/*
   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();
}

Результат:

введите описание изображения здесь