Qt系列文章目錄
文章目錄
- Qt系列文章目錄
- 前言
- 一、Q_DECLARE_METATYPE是什麼?
- 示例代碼
- 二、編譯錯誤
- 三、問題解決
- 四、源碼下載下傳
- 五、運作效果
前言
一、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*)
就是把類型改成指針
四、源碼下載下傳
源碼下載下傳位址