如何使用 Qt 的信号和槽在 C++ 中的状态栏上获取实时变量更新?

How to get live variable updates on a statusbar in C++ with Qt's signals and slots?

我在我的 C++/Qt 应用程序中使用专有驱动程序 API。有一个名为“状态”的对象,它本质上是一个整数值,可用于监视错误。值为 0 表示一切正常,负值表示特定错误。我想编写一个状态栏(使用 Qt 的 QStatusBar),它会在我执行部分代码时实时更新“状态”当前值。我目前拥有的一个简化示例:

DriverInterfaceClass.h

#ifndef DRIVERINTERFACECLASS_H
#define DRIVERINTERFACECLASS_H

#include <QObject>
#include "multicam.h"

class DriverInterfaceClass : public QObject
{
    Q_OBJECT
public:
    DriverInterfaceClass(QObject *parent = nullptr);
    ~DriverInterfaceClass();

private:
    void setStatus(int value);

private:
    MCSTATUS status;

signals:
    void statusChanged(const QString& status, int timeout);
};

#endif // DRIVERINTERFACECLASS_H

DriverInterfaceClass.cpp

#include "driverinterfaceclass.h"

DriverInterfaceClass::DriverInterfaceClass(QObject *parent)
    : QObject(parent)
{
    setStatus(McOpenDriver(NULL));
    status = McSetParamStr(MC_CONFIGURATION, MC_ErrorLog, "error.log");
}

DriverInterfaceClass::~DriverInterfaceClass()
{
    setStatus(McCloseDriver());
}

void DriverInterfaceClass::setStatus(int value)
{
    status = value;
    QString statusStr = QString::number(status);
    emit statusChanged(statusStr, 0);
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "driverinterfaceclass.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    DriverInterfaceClass *driver;
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    driver = new DriverInterfaceClass(this);
    connect(driver, &DriverInterfaceClass::statusChanged, ui->statusbar, &QStatusBar::showMessage);
}

MainWindow::~MainWindow()
{
    delete ui;
}

我在弄清楚如何使用“状态”变量的值更新状态栏时遇到问题。使用此代码,我的状态栏中没有收到任何消息。也许我在初始化变量的方式中遗漏了一些东西?

为了满足您不变的“每当设置状态时发出信号”,您需要使用 setStatus(McSetParamInt(... whatever)); 方法,不要直接修改 status = xxx;(除了 setStatus 方法的主体).然后只需稍微更改 setter 函数即可发出有关要显示在 QStatusBar:

上的所需消息的信息
void DriverInterfaceClass::setStatus(int value)
{
    if (status != value)
    {
        status = value;
        emit statusChanged(myStatusValueToString(status));
    }
}

信号衰减应该是:

signals:
    void statusChanged(const QString& msg);

和你的myStatusValueToString只是一个简单的映射:

QString myStatusValueToString(int status)
{
  if (status == 0) return "OK";
  ... etc ...
}

连接应如下所示:

QObject::connect(driver, &DriverInterfaceClass::statusChanged, statusBar, &QStatusBar::showMessage);

原因

statusChanged 信号受到 unperceived existence 的影响。换句话说,driver 对象尖叫 - STATUS CHAAAAAAANGED!!!!,但没有人听到。这就是原因。

您的代码按以下顺序执行:

driver = new DriverInterfaceClass(this);

然后,作为构造函数的一部分:

setStatus(McOpenDriver(NULL));
status = McSetParamStr(MC_CONFIGURATION, MC_ErrorLog, "error.log");

然后才执行connect语句:

connect(driver, &DriverInterfaceClass::statusChanged, ui->statusbar, &QStatusBar::showMessage);

显然,信号由 setStatus 发出,然后 连接到 ui->statusbar.

的插槽

注:你也直接设置了status的值,没有调用setStatus,即status = McSetParamStr(...,所以信号不是完全发出。但是,由于与上述相同的原因,改为调用 setStatus 也无济于事。

connect 移动到 new 之前会导致编译器错误,因为您无法连接到不存在的东西。

解决方案

不要从构造函数发出信号。当事件发生时这样做。