1. 程式人生 > >QT訊號槽傳遞自定義結構體

QT訊號槽傳遞自定義結構體

QT的訊號槽可以傳遞int, short, double等c語言的常用型別的變數,也可以傳遞如QImage之類的QT支援 的型別。但是如何傳遞一個程式設計師自定義的結構體?

1)在定義結構體之後,要呼叫Q_DECLARE_METATYPE,向QT宣告這個結構體

2)在main.cpp 中,用connect函式 將丟擲此結構體的訊號和接收此結構體的槽函式關聯之前,要呼叫qRegisterMetaType()註冊此結構體

看下面例子 ,在專門定義結構體的標頭檔案裡呼叫Q_DECLARE_METATYPE

#ifndef PROTOCOL_H
#define PROTOCOL_H

#include <QMetaType>

#pragma pack(push, 1)

#if !defined(DEF_ST_ARB_STRUCT)
typedef struct ST_ARB_STRUCT
{
    double d;
    int    i;
    char   c;
} ST_ARB_STRUCT;
#define DEF_ST_ARB_STRUCT

Q_DECLARE_METATYPE(ST_ARB_STRUCT);
//qRegisterMetaType<ST_ARB_STRUCT>();
#endif

#pragma pack(pop)
#endif // PROTOCOL_H

定義類ArbStruct,負責向另一個類發射含有(ST_ARB_STRUCT)的訊號sigArbStruct(ST_ARB_STRUCT)

#ifndef ARBSTRUCT_H
#define ARBSTRUCT_H

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

class ArbStruct : public QObject
{
    Q_OBJECT
public:
    ArbStruct();

signals:
    void            sigArbStruct(ST_ARB_STRUCT);

public slots:
    void            OnRecvEmit(void);
};

#endif // ARBSTRUCT_H

特別地,這個類ArbStruct被封裝為一個lib庫,為的是證明即使發射訊號的類的定義跟接收方的定義並不處於同一個專案裡,訊號槽仍然可以走通。

#include "arbstruct.h"


ArbStruct::ArbStruct()
{
}

void ArbStruct::OnRecvEmit(void)
{
    ST_ARB_STRUCT stMsg;
    stMsg.d = 6.5;
    stMsg.c = 0;
    stMsg.i = -1;

    emit sigArbStruct(stMsg);
}

在主工程裡定義另一個類,負責接收sigArbStruct(ST_ARB_STRUCT)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
signals:
    void            sigClicked(void);
public slots:
    void            OnRecvArbStruct(ST_ARB_STRUCT);
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

接收到ArbStruct發來的訊號後,MainWindow將把訊號內的資料顯示在介面上

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SIGNAL(sigClicked()));
}

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

void MainWindow::OnRecvArbStruct(ST_ARB_STRUCT stMsg)
{
    ui->label->setText(QString("d = %1, i = %2, c = %3")
		.arg(stMsg.d).arg(stMsg.i).arg(int(stMsg.c)));
}

最後在main.cpp裡聯絡兩個類,注意用了qRegisterMetaType:

#include "mainwindow.h"
#include <QApplication>
#include "protocol.h"
#include "arbstruct.h"

#pragma comment(lib, "ArbStruct.lib")

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ArbStruct arb;
    MainWindow w;

    qRegisterMetaType<ST_ARB_STRUCT>("ST_ARB_STRUCT");
    QObject::connect(&arb, SIGNAL(sigArbStruct(ST_ARB_STRUCT)), &w, SLOT(OnRecvArbStruct(ST_ARB_STRUCT)));
    QObject::connect(&w, SIGNAL(sigClicked()), &arb, SLOT(OnRecvEmit()));
    w.show();

    return a.exec();
}

本示例可以在我的資源中下載