如何从非成员函数获取数据到 Qt 中的成员函数?
How to get data from a non-member function into a member function in Qt?
我有一个 Qt 项目(在 Win10 中)需要 ui在我的 MainWindow cpp 文件中保留一个非成员函数。这是一个回调函数,当来自附加传感器的数据到达时,会从外部库自动触发。我喜欢在 MainWindow 小部件(纯文本编辑器)上显示此数据,但当然我无法从我的回调函数访问任何 MainWindow 元素,而且到目前为止还没有信号槽概念起作用。以下是该问题的一个最小示例:
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMutex>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void displayData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
// define global variables
QMutex mutex;
bool new_data_arrived = false;
QString newDataStr;
void newData() {
// This is a callback function triggered when data from a sensor attached via USB arrives
// I want to pass the result as a QString to MainWindow::displayData() to display it on screen
mutex.lock();
new_data_arrived = true;
newDataStr = "new data";
mutex.unlock();
};
void MainWindow::displayData()
{
mutex.lock();
if (new_data_arrived == true) {
new_data_arrived = false;
ui->plainTextEdit->appendPlainText(newDatastr);
}
mutex.unlock();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
函数 MainWindow::displayData()
然后是 运行 循环(但这对我的问题不重要,所以我从上面的最小示例中删除了它……)。
如前所述,newData()
无法访问 MainWindow 的任何元素,这一点很清楚。到目前为止我发现的唯一解决方法是使用如上所示的全局变量,从非成员函数 newData()
获取数据到成员函数 displayData()
。我还包含了一个互斥体以避免可能的共享违规(不知道是否有必要,但它不会伤害...)。
有没有更优雅的方式?原则上,我需要的是信号槽概念,但 newData()
无法发出 MainWindow 的信号,或者将 this
放入函数 newData()
,以便 ui可以访问元素。
您应该使用 QMetaObject::invokeMethod 从非 QObject 插槽(您的回调函数)调用 QObject 的插槽。
这是一个例子:
class MainWindow : public QMainWindow
{
Q_OBJECT
//...
public slots:
void displayData( QString szNewData );
};
//Cpp MainWindow.cpp file
static MainWindow * mainWindowObj = nullptr;
void setMainWindowObj( MainWindow * ptr ){
mainWindowObj = ptr;
}
void newData() {
// This is a callback function triggered when data from a sensor attached via USB arrives
// I want to pass the result as a QString to MainWindow::displayData() to display it on screen
if( mainWindowObj == nullptr )
return;
QMetaObject::invokeMethod( mainWindowObj, //pointer to MainWindow instance (see main.cpp)
"displayData", //slot name
Qt::QueuedConnection, //connection type
Q_ARG( QString, newDataStr ) ); //Param passed to the slot
};
void MainWindow::displayData( QString szNewData )
{
ui->plainTextEdit->appendPlainText( szNewData );
}
//main.cpp file or where MainWindow instance is initialized
void setMainWindowObj( MainWindow * ptr );
int main( int argc, char *argv[] ){
//....
QApplication app(argc, argv);
//....
MainWindow mainWindow;
setMainWindowObj ( &mainWindow );
//....
}
我有一个 Qt 项目(在 Win10 中)需要 ui在我的 MainWindow cpp 文件中保留一个非成员函数。这是一个回调函数,当来自附加传感器的数据到达时,会从外部库自动触发。我喜欢在 MainWindow 小部件(纯文本编辑器)上显示此数据,但当然我无法从我的回调函数访问任何 MainWindow 元素,而且到目前为止还没有信号槽概念起作用。以下是该问题的一个最小示例:
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMutex>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void displayData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
// define global variables
QMutex mutex;
bool new_data_arrived = false;
QString newDataStr;
void newData() {
// This is a callback function triggered when data from a sensor attached via USB arrives
// I want to pass the result as a QString to MainWindow::displayData() to display it on screen
mutex.lock();
new_data_arrived = true;
newDataStr = "new data";
mutex.unlock();
};
void MainWindow::displayData()
{
mutex.lock();
if (new_data_arrived == true) {
new_data_arrived = false;
ui->plainTextEdit->appendPlainText(newDatastr);
}
mutex.unlock();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
函数 MainWindow::displayData()
然后是 运行 循环(但这对我的问题不重要,所以我从上面的最小示例中删除了它……)。
如前所述,newData()
无法访问 MainWindow 的任何元素,这一点很清楚。到目前为止我发现的唯一解决方法是使用如上所示的全局变量,从非成员函数 newData()
获取数据到成员函数 displayData()
。我还包含了一个互斥体以避免可能的共享违规(不知道是否有必要,但它不会伤害...)。
有没有更优雅的方式?原则上,我需要的是信号槽概念,但 newData()
无法发出 MainWindow 的信号,或者将 this
放入函数 newData()
,以便 ui可以访问元素。
您应该使用 QMetaObject::invokeMethod 从非 QObject 插槽(您的回调函数)调用 QObject 的插槽。
这是一个例子:
class MainWindow : public QMainWindow
{
Q_OBJECT
//...
public slots:
void displayData( QString szNewData );
};
//Cpp MainWindow.cpp file
static MainWindow * mainWindowObj = nullptr;
void setMainWindowObj( MainWindow * ptr ){
mainWindowObj = ptr;
}
void newData() {
// This is a callback function triggered when data from a sensor attached via USB arrives
// I want to pass the result as a QString to MainWindow::displayData() to display it on screen
if( mainWindowObj == nullptr )
return;
QMetaObject::invokeMethod( mainWindowObj, //pointer to MainWindow instance (see main.cpp)
"displayData", //slot name
Qt::QueuedConnection, //connection type
Q_ARG( QString, newDataStr ) ); //Param passed to the slot
};
void MainWindow::displayData( QString szNewData )
{
ui->plainTextEdit->appendPlainText( szNewData );
}
//main.cpp file or where MainWindow instance is initialized
void setMainWindowObj( MainWindow * ptr );
int main( int argc, char *argv[] ){
//....
QApplication app(argc, argv);
//....
MainWindow mainWindow;
setMainWindowObj ( &mainWindow );
//....
}