Сигнал C++ не попадает на сторону QML
Я проверял этот пример, и я не могу поймать Qt C++ signal
в QML
, Вот мой UeSettings
заголовок класса:
#ifndef UESETTINGS_H
#define UESETTINGS_H
#include <QObject>
#include <QSqlDatabase>
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>
#include <QDir>
#include <QDateTime>
#include "uedefaults.h"
#include "models/ueprintersmodel.h"
#include "uetypes.h"
/**
* @brief The UeSettings class
*/
class UeSettings : public QObject
{
Q_OBJECT
private:
/**
* @brief m_ueServerAddress
*/
QString m_ueServerAddress;
/**
* @brief m_ueServerPort
*/
QString m_ueServerPort;
/**
* @brief m_ueDatabaseName
*/
QString m_ueDatabaseName;
/**
* @brief m_ueDatabaseUsername
*/
QString m_ueDatabaseUsername;
/**
* @brief m_ueDatabasePassword
*/
QString m_ueDatabasePassword;
/**
* @brief m_ueHostname
*/
QString m_ueHostname;
/**
* @brief m_ueNumberOfTopSalesProductsShown
*/
QString m_ueNumberOfTopSalesProductsShown;
/**
* @brief m_ueDb
*/
QSqlDatabase m_ueDb;
/**
* @brief m_ueAutomaticStockUpdateFromFirstWarehouse
*/
bool m_ueAutomaticStockUpdateFromFirstWarehouse;
/**
* @brief m_ueAutoLogoffWorkerAtBill
*/
bool m_ueAutoLogoffWorkerAtBill;
/**
* @brief m_uePrintersModel
*/
UePrintersModel* m_uePrintersModel;
/**
* @brief ueSetServerAddress
* @param address
*/
inline void ueSetServerAddress(const QString& address)
{ this->m_ueServerAddress=address; }
/**
* @brief ueSetServerPort
* @param port
*/
inline void ueSetServerPort(const QString& port)
{ this->m_ueServerPort=port; }
/**
* @brief ueSetDatabaseName
* @param dbName
*/
inline void ueSetDatabaseName(const QString& dbName)
{ this->m_ueDatabaseName=dbName; }
/**
* @brief ueSetDatabaseUsername
* @param dbUsername
*/
inline void ueSetDatabaseUsername(const QString& dbUsername)
{ this->m_ueDatabaseUsername=dbUsername; }
/**
* @brief ueSetDatabasePassword
* @param dbPassword
*/
inline void ueSetDatabasePassword(const QString& dbPassword)
{ this->m_ueDatabasePassword=dbPassword; }
/**
* @brief ueSetNumberOfTopSalesProductsShown
* @param topN
*/
inline void ueSetNumberOfTopSalesProductsShown(const QString& topN)
{ this->m_ueNumberOfTopSalesProductsShown=topN; }
/**
* @brief ueSetHostname
* @param hostname
*/
inline void ueSetHostname(const QString& hostname)
{ this->m_ueHostname=hostname; }
/**
* @brief ueSetAutomaticStockUpdateFromFirstWarehouse
* @param automaticStockUpdate
*/
inline void ueSetAutomaticStockUpdateFromFirstWarehouse(const bool& automaticStockUpdate)
{ this->m_ueAutomaticStockUpdateFromFirstWarehouse=automaticStockUpdate; }
/**
* @brief ueSetAutoLogoffWorkerAtBill
* @param automaticLogoffWorkerAtBill
*/
inline void ueSetAutoLogoffWorkerAtBill(const bool& automaticLogoffWorkerAtBill)
{ this->m_ueAutoLogoffWorkerAtBill=automaticLogoffWorkerAtBill; }
/**
* @brief uePrintersModel
* @return
*/
inline UePrintersModel* uePrintersModel() const
{ return this->m_uePrintersModel; }
/**
* @brief ueSetPrintersModel
* @param printersModel
*/
inline void ueSetPrintersModel(UePrintersModel* const printersModel=0)
{ this->m_uePrintersModel=printersModel; }
/**
* @brief ueDatabase
* @return
*/
QSqlDatabase ueDatabase()
{ return this->m_ueDb; }
/**
* @brief ueSetDatabase
* @param database
*/
void ueSetDatabase(const QSqlDatabase& database)
{ this->m_ueDb=database; }
/**
* @brief ueCreateDatabase
* @return true if settings database successfully created, otherwise false
*/
bool ueCreateDatabase();
/**
* @brief ueDatabaseExists
* @return true if settings database exists, otherwise false
*/
bool ueDatabaseExists();
public:
/**
* @brief UeSettings
* @param parent
* @param printersModel
*/
explicit UeSettings(QObject *parent = 0,
UePrintersModel* const printersModel=0);
/**
* @brief ~UeSettings
*/
~UeSettings();
Q_INVOKABLE inline QString ueServerAddress() const
{ return this->m_ueServerAddress; }
Q_INVOKABLE inline QString ueServerPort() const
{ return this->m_ueServerPort; }
Q_INVOKABLE inline QString ueDatabaseName() const
{ return this->m_ueDatabaseName; }
Q_INVOKABLE inline QString ueDatabaseUsername() const
{ return this->m_ueDatabaseUsername; }
Q_INVOKABLE inline QString ueDatabasePassword() const
{ return this->m_ueDatabasePassword; }
Q_INVOKABLE inline QString ueHostname() const
{ return this->m_ueHostname; }
Q_INVOKABLE inline bool ueAutomaticStockUpdateFromFirwstWarehouse() const
{ return this->m_ueAutomaticStockUpdateFromFirstWarehouse; }
Q_INVOKABLE inline QString ueNumerOfTopSalesProducts() const
{ return this->m_ueNumberOfTopSalesProductsShown; }
Q_INVOKABLE inline bool ueAutomaticLogoffWorkerAtBill() const
{ return this->m_ueAutoLogoffWorkerAtBill; }
/**
* @brief ueConnectToDatabase
* @return true if connetion to database successfull, otherwise false
*/
bool ueConnectToDatabase();
/**
* @brief ueSaveSettings
* @param address
* @param port
* @param dbName
* @param dbUsername
* @param dbPassword
* @param hostName
* @param autoStockUpdate
* @param topN
* @param autoLogoffWorkerAtBill
* @return true if setitngs were saved in database successfully, otherwise false
*/
Q_INVOKABLE bool ueSaveSettings(const QString& address,
const QString& port,
const QString& dbName,
const QString& dbUsername,
const QString& dbPassword,
const QString& hostName,
const QString& autoStockUpdate,
const QString& topN,
const QString& autoLogoffWorkerAtBill/*,
UeTypePrintersList* const printersList*/);
/**
* @brief ueLoadSettings
* @return true if settings were loaded successfully, otherwise false
*/
Q_INVOKABLE bool ueLoadSettings();
/**
* @brief ueTestConnection
* @param address
* @param port
* @param dbName
* @param dbUsername
* @param dbPassword
* @return true if successfully connected to database, otherwise false
*/
Q_INVOKABLE bool ueTestConnection(const QString& address,
const QString& port,
const QString& dbName,
const QString& dbUsername,
const QString& dbPassword);
signals:
/**
* @brief ueSignalSettingsLoaded
*/
void ueSignalSettingsLoaded();
/**
* @brief ueSignalSettingsSaved
*/
void ueSignalSettingsSaved();
/**
* @brief ueSignalSettingsNotFound
*/
void ueSignalSettingsNotFound();
/**
* @brief ueSignalTestDatabaseConnectionOk
*/
void ueSignalTestDatabaseConnectionOk();
/**
* @brief ueSignalTestDatabaseConnectionFailed
*/
void ueSignalTestDatabaseConnectionFailed();
/**
* @brief ueSignalSettingsDatabaseCreated
*/
void ueSignalSettingsDatabaseCreated();
/**
* @brief ueSignalSettingsDatabaseEmpty
*/
void ueSignalSettingsDatabaseEmpty();
public slots:
};
#endif // UESETTINGS_H
а вот метод, который запускает сигналы ueSignalSettingsDatabaseCreated()
а также ueSignalSettingsDatabaseEmpty
:
bool UeSettings::ueCreateDatabase()
{
bool result=false;
bool connected=false;
if(this->ueDatabase().isOpen())
{
connected=true;
}
else
{
if(this->ueConnectToDatabase())
{
connected=this->ueDatabase().open();
}
else
{
qDebug() << Q_FUNC_INFO
<< this->ueDatabase().lastError().text();
} // if
} // if
if(connected)
{
QSqlQuery queryCreateDatabase(this->ueDatabase());
if(queryCreateDatabase.prepare(UeApplicationSettings::UeSqlQueries::UeCreateSettingsDatabase::QUERY_TURN_ON_FOREIGN_KEYS_SUPPORT))
{
if(queryCreateDatabase.exec())
{
if(queryCreateDatabase.prepare(UeApplicationSettings::UeSqlQueries::UeCreateSettingsDatabase::QUERY_CREATE_TABLE_SETTINGS))
{
if(queryCreateDatabase.exec())
{
if(queryCreateDatabase.prepare(UeApplicationSettings::UeSqlQueries::UeCreateSettingsDatabase::QUERY_CREATE_TABLE_PRINTERS))
{
if(queryCreateDatabase.exec())
{
if(queryCreateDatabase.prepare(UeApplicationSettings::UeSqlQueries::UeCreateSettingsDatabase::QUERY_CREATE_TABLE_SCREEN))
{
if(queryCreateDatabase.exec())
{
result=true;
emit this->ueSignalSettingsDatabaseCreated();
emit this->ueSignalSettingsDatabaseEmpty();
} // if
} // if
}
else
{
qDebug() << Q_FUNC_INFO
<< queryCreateDatabase.lastError().text();
} // if
} // if
else
{
qDebug() << Q_FUNC_INFO
<< queryCreateDatabase.lastQuery()
<< queryCreateDatabase.lastError().text();
} // if
}
else
{
qDebug() << Q_FUNC_INFO
<< queryCreateDatabase.lastError().text();
} // if
}
else
{
qDebug() << Q_FUNC_INFO
<< queryCreateDatabase.lastError().text();
} // if
}
else
{
qDebug() << Q_FUNC_INFO
<< queryCreateDatabase.lastError().text();
} // if
} // if
} // if
return result;
} // ueCreateDatabase
в строках 45 и 46:
emit this->ueSignalSettingsDatabaseCreated();
emit this->ueSignalSettingsDatabaseEmpty();
Теперь экземпляр объекта UeSettings
по имени ueSettings
создается и подвергается QML
в main.cpp
:
UeBluetoothManager* ueBtManager=new UeBluetoothManager(qApp);
UePrintersModel* uePrintersModel=new UePrintersModel(qApp,
ueBtManager);
UeSettings* ueSettings=new UeSettings(qApp,
uePrintersModel);
engine.rootContext()->setContextProperty("ueBtManager",
ueBtManager);
engine.rootContext()->setContextProperty("uePrintersModel",
uePrintersModel);
engine.rootContext()->setContextProperty("ueSettings",
ueSettings);
и я пытаюсь поймать сигналы ueSignalSettingsDatabaseCreated()
а также ueSignalSettingsDatabaseEmpty()
в некоторых QML
файл с:
Connections
{
target: ueSettings
onUeSignalSettingsDatabaseCreated:
{
ueStatusText.text=qsTr("Settings Database Created.");
} // onUeSignalSettingsDatabaseCreated
} // Connections
Connections
{
target: ueSettings
onUeSignalSettingsDatabaseEmpty:
{
ueStatusText.text=qsTr("Settings Database is Empty.");
} // onUeSignalSettingsDatabaseEmpty
} // Connections
Сигналы от C++
сторона выпала, я трижды проверил с отладчиком и не пойман QML
сторона, так как text
свойство не меняется. Зачем? Консоль отладки вообще не выдает никаких предупреждений или ошибок времени выполнения (связанных с проблемой).
3 ответа
Пользователь talamaki был прав, сигнал испускается раньше Connections
объект готов к приему сигнала QML
боковая сторона. Мне удалось решить проблему, подключившись к сигналу QQmlApplicationEngine::objectCreated(), чтобы UeSettings::ueSlotQMLFileLoaded()
Слот и внутри него я проверяю состояние базы данных настроек вместо того, чтобы делать это в конструкторе:
void UeSettings::ueSlotQMLFileLoaded(QObject* object,
const QUrl& url)
{
if(!this->ueConnectToDatabase())
{
qDebug() << Q_FUNC_INFO
<< this->ueDatabase().lastError().text();
} // if
} // ueSlotQMLFileLoaded
QML
часть теперь получает сигнал. Тем не менее, я до сих пор не понимаю, почему, черт возьми, идентичный механизм работает в примере.
Возможно, сигнал испускается раньше Connections
Объект готов к приему сигнала в QML. Если вы добавите метод запроса, например,
Q_INVOKABLE bool UeSettings::isUeSignalSettingsDatabaseCreated()
он, вероятно, возвращает true, когда вы вызываете его со стороны QML.
Если бы я был тобой, я бы использовал свойства, чтобы следовать статусам. Из QML вы можете получить доступ к Q_PROPERTY
используя имя свойства, которое определено в заголовочном файле.
Вам нужно перезапустить qMake, очистить и восстановить, чтобы сигналы были подключены правильно. По крайней мере, это часто так для меня, если у меня есть эта проблема.