其他分享
首页 > 其他分享> > Qt自定义类型信号槽发送接收,以及跨线程发送问题(详细篇)

Qt自定义类型信号槽发送接收,以及跨线程发送问题(详细篇)

作者:互联网

Qt自定义数据类型信号槽传递

1.Qt信号槽是Qt引以为傲的消息传递方式,这里我们不重点讨论信号槽,聊聊自定义数据发送问题,首先我们来看看Qt内置的一些数据类型:

 enum Type {
        Invalid = QMetaType::UnknownType,
        Bool = QMetaType::Bool,
        Int = QMetaType::Int,
        UInt = QMetaType::UInt,
        LongLong = QMetaType::LongLong,
        ULongLong = QMetaType::ULongLong,
        Double = QMetaType::Double,
        Char = QMetaType::QChar,
        Map = QMetaType::QVariantMap,
        List = QMetaType::QVariantList,
        String = QMetaType::QString,
        StringList = QMetaType::QStringList,
        ByteArray = QMetaType::QByteArray,
        BitArray = QMetaType::QBitArray,
        Date = QMetaType::QDate,
        Time = QMetaType::QTime,
        DateTime = QMetaType::QDateTime,
        Url = QMetaType::QUrl,
        Locale = QMetaType::QLocale,
        Rect = QMetaType::QRect,
        RectF = QMetaType::QRectF,
        Size = QMetaType::QSize,
        SizeF = QMetaType::QSizeF,
        Line = QMetaType::QLine,
        LineF = QMetaType::QLineF,
        Point = QMetaType::QPoint,
        PointF = QMetaType::QPointF,
        RegExp = QMetaType::QRegExp,
        RegularExpression = QMetaType::QRegularExpression,
        Hash = QMetaType::QVariantHash,
        EasingCurve = QMetaType::QEasingCurve,
        Uuid = QMetaType::QUuid,
        ModelIndex = QMetaType::QModelIndex,
        PersistentModelIndex = QMetaType::QPersistentModelIndex,
        LastCoreType = QMetaType::LastCoreType,

        Font = QMetaType::QFont,
        Pixmap = QMetaType::QPixmap,
        Brush = QMetaType::QBrush,
        Color = QMetaType::QColor,
        Palette = QMetaType::QPalette,
        Image = QMetaType::QImage,
        Polygon = QMetaType::QPolygon,
        Region = QMetaType::QRegion,
        Bitmap = QMetaType::QBitmap,
        Cursor = QMetaType::QCursor,
        KeySequence = QMetaType::QKeySequence,
        Pen = QMetaType::QPen,
        TextLength = QMetaType::QTextLength,
        TextFormat = QMetaType::QTextFormat,
        Matrix = QMetaType::QMatrix,
        Transform = QMetaType::QTransform,
        Matrix4x4 = QMetaType::QMatrix4x4,
        Vector2D = QMetaType::QVector2D,
        Vector3D = QMetaType::QVector3D,
        Vector4D = QMetaType::QVector4D,
        Quaternion = QMetaType::QQuaternion,
        PolygonF = QMetaType::QPolygonF,
        Icon = QMetaType::QIcon,
        LastGuiType = QMetaType::LastGuiType,

        SizePolicy = QMetaType::QSizePolicy,

        UserType = QMetaType::User,
        LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
    };

可以看到Qt内置类型很丰富,但是有时候并不能满足千奇百怪的需求。碰到一些自定义数据的时候咋办?别急这里还是有几个办法可以解决的。
这里需要非常注意的一点是如果是在同一个线程使用,那么自定义数据类型可以直接发送并在槽里面接受并不会产生什么错误。只有跨线程使用的时候需要考虑自定义数据发送问题,直接使用会产生错误 QObject::connect: Cannot queue arguments of type’‘xxxx’
(1)方法1:引入头文件#include < QMetaType>,使用 qRegisterMetaType<>()
进行元类型注册;

#ifndef VARTEST_H
#define VARTEST_H

#include <QWidget>
#include <QVariant>
#include <QMetaType>

typedef struct _deviceinfo
{
    QString Mac;           //mac
    int  type;             //类型
}DeviceInfo;

namespace Ui {
class VARTest;
}

class VARTest : public QWidget
{
    Q_OBJECT
public:
    explicit VARTest(QWidget *parent = 0);
    ~VARTest();
signals:
    void sigMsg_A(DeviceInfo info);
public slots:
    void sendMsgSlot();
    void sigASlot(DeviceInfo info);
private:
    Ui::VARTest *ui;
};
#endif // VARTEST_H

VARTest::VARTest(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VARTest)
{
    ui->setupUi(this);

    qRegisterMetaType<DeviceInfo>("DeviceInfo");

    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(sendMsgSlot()));
    connect(this,SIGNAL(sigMsg_A(DeviceInfo)),this,SLOT(sigASlot(DeviceInfo)));
}

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

void VARTest::sendMsgSlot()
{
    DeviceInfo m_info;
    m_info.Mac = "4E:3F:3D:48";
    m_info.type = 1;
    emit sigMsg_A(m_info);
}

void VARTest::sigASlot(DeviceInfo info)
{
    qDebug()<<"sigA.Mac:"<<info.Mac;
}

这里我们直接在一个GUI线程里做示例没使用多线程,大家可以在多线程验证一遍
在这里插入图片描述
(2)方法2:使用connect函数的第5个参数Qt::DirectConnection
如:connect(objA,SIGNAL(sig(customType)),objB,SLOT(sigSLOT(customType)),Qt::DirectConnection);
这种方法需要慎用,因为数据在信号所在线程发送以后数据直接在槽所在线程执行,可能会导致跨线程问题。
(3)方法3: 以上方法都有一定的局限性,使用qRegisterMetaType注册元类型,一个信号只能发送一个或几个数据类型,如果需要一个信号发送很多数据类型,这个时候就需要一种通用的数据处理方式。这个时候可以利用QVariant。使用这种方式首先要在数据声明下面使用宏声明Q_DECLARE_METATYPE(DeviceInfo)

#ifndef VARTEST_H
#define VARTEST_H

#include <QWidget>
#include <QVariant>
#include <QMetaType>

typedef struct _deviceinfo
{
    QString Mac;           //mac
    int  type;             //类型
}DeviceInfo;
Q_DECLARE_METATYPE(DeviceInfo)

namespace Ui {
class VARTest;
}

class VARTest : public QWidget
{
    Q_OBJECT
public:
    explicit VARTest(QWidget *parent = 0);
    ~VARTest();
signals:
    void sigMsg_B(int id,QVariant values);
public slots:
    void sendMsgSlot();
    void sigBSlot(int id,QVariant values);
private:
    Ui::VARTest *ui;
};

#endif // VARTEST_H

VARTest::VARTest(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VARTest)
{
    ui->setupUi(this);

    qRegisterMetaType<DeviceInfo>("DeviceInfo");

    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(sendMsgSlot()));
    connect(this,SIGNAL(sigMsg_B(int,QVariant)),this,SLOT(sigBSlot(int,QVariant)));
}

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

void VARTest::sendMsgSlot()
{
    DeviceInfo m_info;
    m_info.Mac = "4E:3F:3D:48";
    m_info.type = 1;
    QVariant values1;
    values1.setValue(m_info);
    emit sigMsg_B(1,values1);

    int m_value = 999;
    QVariant values2;
    values2.setValue(m_value);
    emit sigMsg_B(2,values2);

    QString str("真有意思!");
    QVariant values3;
    values3.setValue(str);
    emit sigMsg_B(3,values3);

}

void VARTest::sigBSlot(int id,QVariant values)
{
    switch (id) {
    case 1:
    {
        DeviceInfo m_info = values.value<DeviceInfo>();
        qDebug()<<"sigB Mac:"<<m_info.Mac;
        break;
    }
    case 2:
    {
        qDebug()<<"sigB int:"<<values.toInt();
        break;
    }
    case 3:
    {
        qDebug()<<"sigB QString:"<<values.toString();
        break;
    }
    default:
        break;
    }
}

在这里插入图片描述
这种方法非常适合自定义的数据非常多的情况,可以用一个信号发送进行集中处理,能发送自定义数据同时兼顾内置数据类型。

作者:费码程序猿
欢迎技术交流:QQ:255895056
转载请注明出处,如有不当欢迎指正

标签:info,Qt,自定义,void,DeviceInfo,发送,QMetaType,VARTest,ui
来源: https://blog.csdn.net/haohaohaihuai/article/details/104669903