QObject::connect: 没有这样的信号运行时警告 - 找不到原因

Posted

技术标签:

【中文标题】QObject::connect: 没有这样的信号运行时警告 - 找不到原因【英文标题】:QObject::connect: No such signal runtime warning - cannot find the reasion for 【发布时间】:2016-08-15 10:08:38 【问题描述】:

我正在开发基于this example 的异步多线程服务器。现在,我采用以下方法:

void UeClient::ueSlotReadyRead()

    QList<QVariant> incomingData=QList<QVariant>();
    QByteArray incomingMessage=this->ueSocket()->readAll();

    UePosCommProtocolArch::UeCommand incomingCommand=UePOSCommProtocol::ueDecodeCommand(incomingMessage,
                                                                                        incomingData);

    UeTask* ueTask=new UeTask("testDb",
                              "testUsername",
                              "testPassword",
                              "localhost",
                              "3306",
                              incomingCommand);

    connect(ueTask,
            SIGNAL(ueSignalTaskFinished(UePosCommProtocolArch::UeCommand,
                                        QByteArray)),
            this,
            SLOT(ueSlotFetchData(UePosCommProtocolArch::UeCommand,
                                 QByteArray)),
            Qt::QueuedConnection);

    QThreadPool::globalInstance()->start(ueTask);
   // ueSlotReadyRead

我在QtCreator 中收到以下运行时警告/错误:

QObject::connect: No such signal UeTask::ueSignalTask​​Finished(UePosCommProtocolArch::UeCommand, QByteArray) in ../../../net/ueclient.cpp:55

这里是UeTask类头文件,从中我们可以看到ueSignalTaskFinished(UePosCommProtocolArch::UeCommand&amp; executedCommand, QByteArray&amp; fetchedData);IS声明

#ifndef UETASK_H
#define UETASK_H

#include <QObject>
#include <QRunnable>
#include <QSqlDatabase>
#include <QSqlError>
#include <QUuid>
#include <QString>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>
#include <QJsonDocument>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
#include <QByteArray>

#include "../../uePOSCommProtocol/uecommands.h"
#include "database/models/uefieldindexes.h"
#include "database/models/uequeries.h"

/*!
 * \brief The UeTask class
 */
class UeTask : public QObject,
               public QRunnable

    Q_OBJECT

private:
    /*!
     * \brief m_ueDatabaseName
     */
    QString m_ueDatabaseName;

    /*!
     * \brief m_ueUserName
     */
    QString m_ueUserName;

    /*!
     * \brief m_uePassword
     */
    QString m_uePassword;

    /*!
     * \brief m_ueHostName
     */
    QString m_ueHostName;

    /*!
     * \brief m_uePort
     */
    QString m_uePort;

    /*!
     * \brief m_ueCommand
     */
    UePosCommProtocolArch::UeCommand m_ueCommand;

    /*!
     * @brief ueDatabaseName
     * @return database name
     */
    inline const QString& ueDatabaseName() const
         return this->m_ueDatabaseName; 

    /*!
     * @brief ueDatabaseUserName
     * @return database user name
     */
    inline const QString& ueDatabaseUserName() const
         return this->m_ueUserName; 

    /*!
     * @brief ueDatabasePassword
     * @return database password
     */
    inline const QString& ueDatabasePassword() const
         return this->m_uePassword; 

    /*!
     * @brief ueDatabasHost
     * @return database host name
     */
    inline const QString& ueDatabasHost() const
         return this->m_ueHostName; 

    /*!
     * @brief uePort
     * @return database host port
     */
    inline const QString& ueDatabaseHostPort() const
         return this->m_uePort; 

    /*!
     * \brief ueCommand
     * \return task command
     */
    inline UePosCommProtocolArch::UeCommand& ueCommand()
         return this->m_ueCommand; 

    /*!
     * @brief ueSetDatbaseName
     * @param name
     */
    inline void ueSetDatbaseName(const QString& name)
         this->m_ueDatabaseName=name; 

    /*!
     * @brief ueSetDatabaseUserName
     * @param userName
     */
    inline void ueSetDatabaseUserName(const QString& userName)
         this->m_ueUserName=userName; 

    /*!
     * @brief ueSetDatabasePassword
     * @param password
     */
    inline void ueSetDatabasePassword(const QString& password)
         this->m_uePassword=password; 

    /*!
     * @brief ueSetDatabaseHostName
     * @param hostName
     */
    inline void ueSetDatabaseHostName(const QString& hostName)
         this->m_ueHostName=hostName; 

    /*!
     * @brief ueSetDatabaseHostPort
     * @param port
     */
    inline void ueSetDatabaseHostPort(const QString& port)
         this->m_uePort=port; 

    /*!
     * \brief ueSetCommand
     * \param command
     */
    inline void ueSetCommand(const UePosCommProtocolArch::UeCommand& command)
         this->m_ueCommand=command; 

public:
    /*!
     * @brief UeTask
     */
    explicit UeTask(const QString& databaseName,
                    const QString& userName,
                    const QString& password,
                    const QString& hostName,
                    const QString& port,
                    const UePosCommProtocolArch::UeCommand& command);

protected:
    /*!
     * @brief run
     */
    void run();

signals:
    /*!
     * \brief ueSignalTaskFinished
     * \param executedCommand
     * \param fetchedData
     */
    void ueSignalTaskFinished(UePosCommProtocolArch::UeCommand& executedCommand,
                              QByteArray& fetchedData);

    /*!
     * @brief ueSignalDatabaseConnectionOk
     */
    void ueSignalDatabaseConnectionOk();

    /*!
     * @brief ueSignalDatabaseConnectionError
     * @param error
     */
    void ueSignalDatabaseConnectionError(const QSqlError& error);
;

#endif // UETASK_H

为什么我会收到这个运行时警告/错误,而signal 连接到slot?这可能是一个愚蠢的错误,但我已经为这个错误苦苦挣扎了几个小时......

【问题讨论】:

【参考方案1】:

您的信号签名与您在SIGNAL 宏中编写的签名不匹配——这些是非常量引用:

SIGNAL(ueSignalTaskFinished(UePosCommProtocolArch::UeCommand&, // reference
                            QByteArray&)), //ditto

使用非常量引用作为信号参数已经足够可疑了,将它们与排队连接一起使用肯定是错误的。您想在这里实现什么目标?

【讨论】:

使用这两个参数,我想将数据从ueSignalTaskFinished 传输到slot,这样我就可以处理获取的数据,这是错误的做法吗?! 那么为什么不通过引用传递给 const 呢?【参考方案2】:

信号签名是引用类型(UePosCommProtocolArch::UeCommand&, QByteArray&)。您正在尝试使用另一个签名将信号连接到插槽。

【讨论】:

请注意,如果它是 const 引用,它会匹配【参考方案3】:

我已经设法通过@peppe 的回答解决了这个问题,并且我已将const 添加到SIGNAL 的声明中:

#ifndef UETASK_H
#define UETASK_H

#include <QObject>
#include <QRunnable>
#include <QSqlDatabase>
#include <QSqlError>
#include <QUuid>
#include <QString>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>
#include <QJsonDocument>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
#include <QByteArray>

#include "../../uePOSCommProtocol/uecommands.h"
#include "database/models/uefieldindexes.h"
#include "database/models/uequeries.h"

/*!
 * \brief The UeTask class
 */
class UeTask : public QObject,
               public QRunnable

    Q_OBJECT

private:
    /*!
     * \brief m_ueDatabaseName
     */
    QString m_ueDatabaseName;

    /*!
     * \brief m_ueUserName
     */
    QString m_ueUserName;

    /*!
     * \brief m_uePassword
     */
    QString m_uePassword;

    /*!
     * \brief m_ueHostName
     */
    QString m_ueHostName;

    /*!
     * \brief m_uePort
     */
    QString m_uePort;

    /*!
     * \brief m_ueCommand
     */
    UePosCommProtocolArch::UeCommand m_ueCommand;

    /*!
     * @brief ueDatabaseName
     * @return database name
     */
    inline const QString& ueDatabaseName() const
         return this->m_ueDatabaseName; 

    /*!
     * @brief ueDatabaseUserName
     * @return database user name
     */
    inline const QString& ueDatabaseUserName() const
         return this->m_ueUserName; 

    /*!
     * @brief ueDatabasePassword
     * @return database password
     */
    inline const QString& ueDatabasePassword() const
         return this->m_uePassword; 

    /*!
     * @brief ueDatabasHost
     * @return database host name
     */
    inline const QString& ueDatabasHost() const
         return this->m_ueHostName; 

    /*!
     * @brief uePort
     * @return database host port
     */
    inline const QString& ueDatabaseHostPort() const
         return this->m_uePort; 

    /*!
     * \brief ueCommand
     * \return task command
     */
    inline UePosCommProtocolArch::UeCommand& ueCommand()
         return this->m_ueCommand; 

    /*!
     * @brief ueSetDatbaseName
     * @param name
     */
    inline void ueSetDatbaseName(const QString& name)
         this->m_ueDatabaseName=name; 

    /*!
     * @brief ueSetDatabaseUserName
     * @param userName
     */
    inline void ueSetDatabaseUserName(const QString& userName)
         this->m_ueUserName=userName; 

    /*!
     * @brief ueSetDatabasePassword
     * @param password
     */
    inline void ueSetDatabasePassword(const QString& password)
         this->m_uePassword=password; 

    /*!
     * @brief ueSetDatabaseHostName
     * @param hostName
     */
    inline void ueSetDatabaseHostName(const QString& hostName)
         this->m_ueHostName=hostName; 

    /*!
     * @brief ueSetDatabaseHostPort
     * @param port
     */
    inline void ueSetDatabaseHostPort(const QString& port)
         this->m_uePort=port; 

    /*!
     * \brief ueSetCommand
     * \param command
     */
    inline void ueSetCommand(const UePosCommProtocolArch::UeCommand& command)
         this->m_ueCommand=command; 

public:
    /*!
     * @brief UeTask
     */
    explicit UeTask(const QString& databaseName,
                    const QString& userName,
                    const QString& password,
                    const QString& hostName,
                    const QString& port,
                    const UePosCommProtocolArch::UeCommand& command);

protected:
    /*!
     * @brief run
     */
    void run();

signals:
    /*!
     * \brief ueSignalTaskFinished
     * \param executedCommand
     * \param fetchedData
     */
    void ueSignalTaskFinished(const UePosCommProtocolArch::UeCommand& executedCommand,
                              const QByteArray& fetchedData);

    /*!
     * @brief ueSignalDatabaseConnectionOk
     */
    void ueSignalDatabaseConnectionOk();

    /*!
     * @brief ueSignalDatabaseConnectionError
     * @param error
     */
    void ueSignalDatabaseConnectionError(const QSqlError& error);
;

#endif // UETASK_H

然后我必须register meta type 与:

qRegisterMetaType<UePosCommProtocolArch::UeCommand>("UePosCommProtocolArch::UeCommand");

在上层类的构造函数中:

UeClient::UeClient(QObject *parent,
                   UeSettings* const settings)
    : QObject(parent)

    qRegisterMetaType<UePosCommProtocolArch::UeCommand>("UePosCommProtocolArch::UeCommand");

    QThreadPool::globalInstance()->setMaxThreadCount(10);

    this->ueSetSettings(settings);
   // constructor

现在它可以工作了!

【讨论】:

以上是关于QObject::connect: 没有这样的信号运行时警告 - 找不到原因的主要内容,如果未能解决你的问题,请参考以下文章

QObject::connect: 没有这样的信号错误 C++

QObject::connect: 没有这样的信号progressbarV::keyReleaseEvent()

QObject::connect: 没有这样的信号运行时警告 - 找不到原因

如果在调用 QObject::connect() 之前发出信号,如何避免竞争?

QObject::connect: 需要括号,信号 QSerialPort::readyRead in ..\voltage_sensor\dialop.cpp:41

如何修复QObject::connect:没有这样的插槽..将发送者连接到同一类中的插槽时[重复]