如何使用 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
之前会导致编译器错误,因为您无法连接到不存在的东西。
解决方案
不要从构造函数发出信号。当事件发生时这样做。
我在我的 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
之前会导致编译器错误,因为您无法连接到不存在的东西。
解决方案
不要从构造函数发出信号。当事件发生时这样做。