Emit Signal в конструкторе зарегистрированного типа Qml не работает - PullRequest
1 голос
/ 27 марта 2019

Я настраиваю класс менеджера ресурсов для своего приложения. чтобы управлять всем состоянием ресурсов, мне нужно испустить сигнал из конструктора, если не удается поймать ресурс.

На самом деле я хочу испустить сигнал от конструктора производного класса QObject, который зарегистрирован для qml через qmlRegisterType.

это код, который я тестировал на Linux, работающем под MySql и Qt 5.12.2. но сигнал излучения не работает.

myresoureces.cpp ---- мой класс, управляющий ресурсами

MyResource::MyResource(QObject *parent) : QObject(parent)
{
    if(!openResource()) {
        // qDebug() << "Check Permission of FileSystem For Example.";
        emit openResourceFailed("Check Permission of FileSystem For Example.");
    }
}

bool MyResource::openResource()
{
    // on situation opening resource failed
    return false;
}


main.qml ---- использование его в qml

// ...
import My.Company.Core 1.0
// ...

    MyResource {
        onOpenResourceFailed: {
            msgDialog.title = "Open Resource Failed!"
            msgDialog.text = error
            msgDialog.open()
        }
    }

    MessageDialog {
        id: msgDialog
    }

// ...

main.cpp ---- где я регистрирую класс

qmlRegisterType<MyResource>("My.Company.Core", 1, 0, "MyResource");

Я ожидаю, что откроется диалог сообщений, но ничего не произошло.

1 Ответ

1 голос
/ 27 марта 2019

Сигналы будут вызывать методы, которые подключены во время излучения сигнала, в вашем случае конструктор не подключен ни к одному слоту, поэтому данные будут потеряны, возможное решение состоит в использовании QTimer::singleShot(0, ...) для испускаться через мгновение после создания:

MyResource::MyResource(QObject *parent=nullptr) : QObject(parent){
    if(!openResource()) {
        QTimer::singleShot(0, this, [this](){
            emit openResourceFailed("Check Permission of FileSystem For Example.");
        });
    }
}

Другим альтернативным решением является использование QQmlParserStatus в качестве интерфейса и передача сигнала в методе componentComplete():

*. Ч

#ifndef MYRESOURCE_H
#define MYRESOURCE_H

#include <QObject>
#include <QQmlParserStatus>

class MyResource: public QObject, public QQmlParserStatus
{
    Q_OBJECT
    Q_INTERFACES(QQmlParserStatus)
public:
    MyResource(QObject *parent=nullptr);
    void classBegin();
    void componentComplete();
signals:
    void openResourceFailed(const QString & error);
private:
    bool openResource();
};


#endif // MYRESOURCE_H

*. Каст

#include "myresource.h"

MyResource::MyResource(QObject *parent) : QObject(parent){}

void MyResource::classBegin(){}

void MyResource::componentComplete(){
    if(!openResource()) {
        emit openResourceFailed("Check Permission of FileSystem For Example.");
    }
}

bool MyResource::openResource(){
    // on situation opening resource failed
    return false;
}
...