Как использовать 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();
}
Результат:
![введите описание изображения здесь]()