Как вызвать слот qt асинхронно?
Точнее как выгрузить QObject с сигналами так чтоб интерфейс выполнялся в отдельном потоке, а Ccode в отдельном. Обратная связь подойдет через сигналы или через колбэки или любая другая, но чтоб в сишном коде не привязываться к интерфейсу.
Сейчас выгруженно в таком виде через qmltypes (при выгрузке через setContextProperty тоже самое)
class Ccode : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_NAMED_ELEMENT(Ccode)
QML_SINGLETON
public slots:
void start();
signals:
void started();
}
Интерфейс зависает при вызове Ccode.start()
Если выносить в тред
QQmlEngine: Illegal attempt to connect to Ccode(0x7fff658c3e20) that is in a different thread than the QML engine QQmlApplicationEngine(0x7fff658c3e00.
Соединение хочется выполнить в QML
ApplicationWindow {
Connections {
target: Ccode
function onStarted() {
console.log("started")
}
}
Component.onCompleted: {
Ccode.start()
}
}
В функции start работа с железом. Ну для простоты примера:
void Ccode::start() {
QThread::sleep(5);
emit started();
}
Ответы (2 шт):
Немного изменил код, вместо сингтона сделал обычный класс и классическую его регистрацию в qml:
class Ccode : public QObject
{
Q_OBJECT
public slots:
void start() {
qDebug() << "start";
}
signals:
void started();
};
main.cpp:
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
qmlRegisterType<Ccode>("com", 1, 0, "Ccode");
engine.load(url);
return app.exec();
}
Теперь main.qml:
ApplicationWindow {
Ccode {
id: ccode
}
Connections {
target: ccode
function onStarted() {
console.log("started")
}
}
Component.onCompleted: {
ccode.start()
}
}
И все работает как часы ( кроме работы сигнала Ccode::started / qml::onStarted - это не тестировал )
class Ccode : public QObject
{
Q_OBJECT
public slots:
void start();
signals:
void started();
}
Оборачивается внешним классом, где уже сигналы переэмитятся в новый поток:
class CcodeProxy : public QObject
Q_OBJECT
QML_ELEMENT
QML_NAMED_ELEMENT(Ccode)
QML_SINGLETON
signals:
void _start();
void started();
public slots:
void start(){ emit _start(); };
void _started() { emit started(); };
public:
Ccode cc;
QThread mythread;
explicit CcodeProxy(QObject *parent = nullptr) {
cc.moveToThread(mythread);
connect(this, &CcodeProxy::_start, &cc, &Ccode::start, Qt::QueuedConnection);
connect(&cc, &Ccode::started, this, &CcodeProxy::_started, Qt::QueuedConnection);
};
};