Qt connect - 对象在发出连接之前发出信号

Qt connect - object emits signal before connect is issued

我关注main.cpp:

#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>

#include "database/uepeoplemodel.h"
#include "core/uestatus.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    UeStatus* ueApplicationStatus=new UeStatus(qApp);
    UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

    QObject::connect(uePeopleModel,
                     SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

    engine.rootContext()->setContextProperty("uePeopleModel",
                                             uePeopleModel);
    engine.rootContext()->setContextProperty("ueApplicationStatus",
                                             ueApplicationStatus);
    engine.addImageProvider(QLatin1String("uePeopleModel"),
                            uePeopleModel);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

现在,在 main.cpp 中,我从 类 创建了两个对象:

UeStatus* ueApplicationStatus=new UeStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

然后我将来自 UePeopleModel 的信号连接到 ueApplicationStatus 中的插槽:

QObject::connect(uePeopleModel,
    SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)), 
    ueApplicationStatus,
    SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

问题是在创建 uePeopleModel 时,信号在构造函数中发出:

UePeopleModel::UePeopleModel(QObject* parent)
    : QSqlQueryModel(parent),
      QQuickImageProvider(QQmlImageProviderBase::Image,
                          QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
    if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
                                                 Qt::CaseInsensitive))
    {
        this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
                                                      UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
    }   // if

    this->ueDatabase().setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    this->ueDatabase().setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    this->ueDatabase().setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    this->ueDatabase().setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);

    if(this->ueDatabase().open())
    {
        emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       this->ueDatabase());
/*
        if(this->lastError().isValid())
            qDebug() << this->lastError();
*/
    }
    else
    {
        emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
//        qDebug() << this->ueDatabase().lastError();
    }

//    qDebug() << this->ueDatabase().connectionNames();
}   // default constructor

connect 发出之前,因此 ueApplicationStatus 对象没有捕捉到插槽。有谁知道如何摆脱这种情况?

您不应该使用构造函数打开与数据库的连接。

仅使用构造函数来实例化其他类、初始化变量、分配内存等。

在你的情况下,你的构造函数应该用于初始化数据库,但你可以创建另一个方法:

if(this->ueDatabase().open())
    {
        emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       this->ueDatabase());
    }
    else
    {
        emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
}

此方法将在您的 main.cpp 中的 connect 之后调用。

我已经通过添加方法 void ueConnectToDatabase() 解决了这个问题,并将构造函数的内容移入其中并将 main.cpp 重新定义为:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    UeStatus* ueApplicationStatus=new UeStatus(qApp);
    UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

    QObject::connect(uePeopleModel,
                     SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

    uePeopleModel->ueConnectToDatabase();

    engine.rootContext()->setContextProperty("uePeopleModel",
                                             uePeopleModel);
    engine.rootContext()->setContextProperty("ueApplicationStatus",
                                             ueApplicationStatus);
    engine.addImageProvider(QLatin1String("uePeopleModel"),
                            uePeopleModel);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

现在创建了对象,连接了信号和插槽,然后连接到数据库。