Qt代码改错:解决'QMetaObject::connectSlotsByName: No matching signal for...'错误

在使用Qt进行GUI开发时,经常会遇到'QMetaObject::connectSlotsByName: No matching signal for...'的错误提示。这个错误通常是由于信号和槽函数的连接不正确导致的。本文将通过一个具体的例子,介绍如何解决这个错误,并对代码进行优化。

错误分析

这个错误提示表明Qt的自动连接机制无法找到与槽函数on_modeComboBox_currentIndexChanged(int)相匹配的信号。

解决方法

  1. **检查信号和槽函数的命名是否一致。**自动连接机制要求槽函数的命名必须遵循on_<objectName>_<signalName>(<arguments>)的格式。在这个例子中,槽函数的命名是正确的。

  2. **检查信号和槽函数的参数类型和数量是否匹配。**在这个例子中,信号currentIndexChanged有两个重载版本,一个是void currentIndexChanged(int index),另一个是void currentIndexChanged(const QString &text)。而槽函数on_modeComboBox_currentIndexChanged(int index)的参数类型是int,因此需要使用QOverload指定连接到currentIndexChanged(int index)信号:

connect(ui->modeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
        this, &UsersWidget::on_modeComboBox_currentIndexChanged);

代码优化

除了解决上述错误之外,还可以对代码进行一些优化,以提高代码的可读性和效率。

1. 使用信号和槽函数传递数据

可以将槽函数修改为如下形式,使用信号传递下拉框的当前文本:

// UsersWidget.h
signals:
    void modeChanged(const QString &mode); // 添加信号

// UsersWidget.cpp
void UsersWidget::on_modeComboBox_currentIndexChanged(int index)
{
    QString mode = ui->modeComboBox->currentText();
    emit modeChanged(mode);
}

2. 优化数据库操作

updateSmartHomeStatus函数中,每次更新数据都会重新打开数据库连接,这样会降低效率。可以将数据库连接初始化放到程序启动时执行一次,避免重复打开连接。

void updateSmartHomeStatus(int userId, QString deviceName, QString devicestate, QString newValue)
{
    // Sqlite::sqlite_init(); // 不需要每次都初始化
    QSqlQuery query;
    // ...
}

3. 完善数据库查询逻辑

statusUid函数中,如果查询到数据,应该返回true,否则返回false

bool statusUid(int userId)
{
    // ...
    if (!query.exec()) {
        // ...
    }
    else {
        if (!query.next()) {
            qDebug() << 'No data found!';
            return false;
        }
        else {
            qDebug() << 'Data found!';
            return true;
        }
    }
}

完整的代码示例

// UsersWidget.h
#ifndef USERSWIDGET_H
#define USERSWIDGET_H

#include <QWidget>
#include <QComboBox>

namespace Ui {
class UsersWidget;
}

class UsersWidget : public QWidget
{
    Q_OBJECT

public:
    explicit UsersWidget(int userid, QWidget *parent = nullptr);
    ~UsersWidget();
    void displayUsersWidget();

protected:
    void closeEvent(QCloseEvent *);

signals:
    void modeChanged(const QString &mode); // 添加信号

private slots:
    void on_modeComboBox_currentIndexChanged(int index);

private:
    Ui::UsersWidget *ui;
    int userid;
};

#endif // USERSWIDGET_H

// UsersWidget.cpp
#include 'userswidget.h'
#include 'ui_userswidget.h'
// ...

UsersWidget::UsersWidget(int userid, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UsersWidget)
{
    // ...
    connect(ui->modeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &UsersWidget::on_modeComboBox_currentIndexChanged);
    // ...
}

// ...

void UsersWidget::on_modeComboBox_currentIndexChanged(int index)
{
    QString mode = ui->modeComboBox->currentText();
    emit modeChanged(mode);
}

// ...

void updateSmartHomeStatus(int userId, QString deviceName, QString devicestate, QString newValue)
{
    // ...
    QString sql = QString('INSERT INTO Status (uid, device_name, device_state, value) VALUES (:userId, :deviceName, :devicestate, :newValue)');
    query.prepare(sql);
    query.bindValue(':userId', userId);
    query.bindValue(':deviceName', deviceName);
    query.bindValue(':devicestate', devicestate);
    query.bindValue(':newValue', newValue);
    // ...
}

bool statusUid(int userId)
{
    // ...
    if (!query.exec()) {
        // ...
    }
    else {
        if (!query.next()) {
            qDebug() << 'No data found!';
            return false;
        }
        else {
            qDebug() << 'Data found!';
            return true;
        }
    }
}

总结

本文介绍了Qt中解决'QMetaObject::connectSlotsByName: No matching signal for...'错误的方法,并提供了一些代码优化建议。在进行Qt开发时,请务必注意信号和槽函数的命名、参数类型和数量,以及数据库操作的效率。

Qt信号与槽机制:解决'QMetaObject::connectSlotsByName: No matching signal for...'错误

原文地址: https://www.cveoy.top/t/topic/fBcD 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录