Как использовать SIGNAL и SLOT без использования QObject? - PullRequest
15 голосов
/ 21 сентября 2011

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

Мне нужны функциональные возможности СИГНАЛОВ и СЛОТОВ в моем классе, но я полагаю, что невозможно получить без QObject?

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

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

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

Так что мой класс плеч выглядит так:

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

11 голосов
/ 21 сентября 2011

Если вам нужен копируемый объект с 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 голосов
/ 21 сентября 2011

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

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

2 голосов
/ 01 января 2017

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

connect(&timer, &QTimer::finished,
        &instanceOfMyClass, &MyClass::fancyMemberFunction);
2 голосов
/ 21 сентября 2011

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

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

1 голос
/ 02 декабря 2017

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

Результат:

enter image description here

...