如何从非成员函数获取数据到 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 );
    
    //....
}