Qt系列文章目录
前言
一、Q_DECLARE_METATYPE是什么?
官网解释
只提供公共默认构造函数、公共复制构造函数和公共析构函数,该宏就会使QMetaType知道类型类型类型。需要将类型类型类型用作QVariant中的自定义类型。
此宏要求类型在使用时是完全定义的类型。对于指针类型,还需要完全定义指向类型。与Q_DECLARE_OPAQUE_POINTER()结合使用,注册指向已声明类型的指针。
理想情况下,这个宏应该放在类或结构的声明下面。如果不可能,可以将其放入私有头文件中,每次在QVariant中使用该类型时都必须包含该头文件。
添加Q_DECLARE_METATYPE()使所有基于模板的函数(包括QVariant)都知道该类型。请注意,如果您打算在排队信号和插槽连接或QObject的属性系统中使用该类型,则还必须调用qRegisterMetaType(),因为名称在运行时解析。
此示例显示了Q_DECLARE_METATYPE()的典型用例:
struct MyStruct
{
int i;
...
};
Q_DECLARE_METATYPE(MyStruct)
在实际代码中,自己手动添加构造函数、拷贝构造函数、析构函数也是可以的例如:
头文件
#ifndef USER_H
#define USER_H
#include<QObjectUserData>
struct UserTest : public QObjectUserData
{
public:
UserTest();
~UserTest();
UserTest(const UserTest& other);
public:
QString m_imgPath;
int m_itemType;
};
Q_DECLARE_METATYPE(UserTest)
#endif // USER_H
实现文件
#include "User.h"
UserTest::UserTest()
{
}
UserTest::~UserTest()
{
}
UserTest::UserTest(const UserTest& other)
{
m_imgPath = other.m_imgPath;
m_itemType = other.m_itemType;
}
示例代码
头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeWidget>
#include <QGridLayout>
#include <User.h>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
QTreeWidget *m_tree;
QTreeWidgetItem *m_treeItem;
UserTest* m_data;
UserTest* m_data1;
QWidget* m_widget;
QGridLayout* m_layout;
void initUi();
Q_SIGNALS:
void clickSendTreeItemData(QTreeWidgetItem* item, int column);
public Q_SLOTS:
void recvTreeItemData(QTreeWidgetItem* item, int column);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
实现文件
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include <QGridLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_widget = new QWidget();
m_tree = new QTreeWidget;
m_tree->setColumnCount(1);
m_tree->setHeaderLabel(u8"英雄");
m_treeItem = new QTreeWidgetItem(m_tree);
m_treeItem->setText(0, u8"放逐之刃·瑞雯");
m_data = new UserTest();
m_data->m_imgPath = ":/Picture/Images/ruiwen.png";
m_data->m_itemType = 1;
m_treeItem->setData(0, Qt::UserRole + 1, QVariant::fromValue(m_data));
m_tree->addTopLevelItem(m_treeItem);
QTreeWidgetItem* itemBountyHunter = new QTreeWidgetItem(m_tree);
itemBountyHunter->setText(0, u8"赏金猎人·厄运小姐");
m_data1 = new UserTest;
m_data1->m_imgPath = ":/Picture/Images/ruiwen.png";
m_data1->m_itemType = 1;
itemBountyHunter->setData(0, Qt::UserRole + 2, QVariant::fromValue(m_data1));
// m_layout = new QGridLayout;
// m_layout->addWidget(m_tree, 0, 0);
// m_widget->setLayout(m_layout);
// m_widget->show();
m_tree->show();
void (QTreeWidget::*curChangeSignal)(QTreeWidgetItem *item, int column) = &QTreeWidget::itemClicked;
void (MainWindow::*on_curChangeSlot)(QTreeWidgetItem* item, int column) = &MainWindow::recvTreeItemData;
// QObject::connect(m_tree, MainWindow::clickSendTreeItemData(QTreeWidgetItem* item, int column), this, &MainWindow::recvTreeItemData);
connect(m_tree, curChangeSignal, this, on_curChangeSlot);
connect(m_tree, curChangeSignal, this, &MainWindow::recvTreeItemData);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::recvTreeItemData(QTreeWidgetItem* item, int column)
{
QString name = item->data(0, Qt::UserRole + 1).toString();
int type = item->data(0, Qt::UserRole + 1).toInt();
qDebug() << "英雄:" << name << "位置" << type;
}
main
#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
二、编译错误
编译时发现错误
error: C2338: Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt’s meta-object system
网上大部分解答都是添加:Q_DECLARE_METATYPE(type)
可我的代码中明明就有:Q_DECLARE_METATYPE(UserTest)
三、问题解决
非常感谢 BloodRose 给出的解答
今天遇到了莫名其妙的编译错误,原因是我用QVariant设置一个自定义指针类型的Data,这时就需要Q_DECLARE_METATYPE(Type*)了,如果设置了Q_DECLARE_METATYPE(Type),Qt只能识别Type类型,而未能识别其指针类型!!!
另外自定义类型中一定要有默认构造函数,如果已经显式的定义了带有无默认参数的构造函数则需要另外写上默认构造函数 Test(){}。
还有为保证不出其他莫名其妙的错误,最好在类定义的头文件中加上#include ,保证编译器能够识别该宏。
在我的代码中修改
把:Q_DECLARE_METATYPE(UserTest)
改成
Q_DECLARE_METATYPE(UserTest*)
就是把类型改成指针
四、源码下载
五、运行效果