QT信號和槽怎么傳輸自己定義的數據結構

在 Qt 中,信號(Signal)和槽(Slot)機制默認支持許多內置類型(如?intQStringQList?等),但如果要傳輸?自定義數據結構(如結構體、類對象),需要額外處理。以下是幾種實現方式:


1. 使用?QVariant?包裝自定義類型(推薦)

QVariant?是 Qt 的通用數據容器,可以存儲任意類型。要讓?QVariant?支持自定義類型,需要:

  1. 注冊自定義類型Q_DECLARE_METATYPE?+?qRegisterMetaType)。

  2. 在信號/槽中使用?QVariant?作為參數類型。

示例:傳輸自定義結構體

#include <QObject>
#include <QVariant>// 1. 定義自定義數據結構
struct Person {QString name;int age;
};// 2. 聲明元類型支持(必須在頭文件或全局作用域)
Q_DECLARE_METATYPE(Person)class DataSender : public QObject {Q_OBJECT
public:void sendData() {Person p {"Alice", 25};emit dataSent(QVariant::fromValue(p)); // 轉換為 QVariant}signals:void dataSent(QVariant personData); // 信號參數用 QVariant
};class DataReceiver : public QObject {Q_OBJECT
public slots:void onDataReceived(QVariant data) {Person p = data.value<Person>(); // 從 QVariant 提取qDebug() << "Received:" << p.name << p.age;}
};int main() {// 3. 注冊元類型(必須在連接信號槽前調用)qRegisterMetaType<Person>("Person");DataSender sender;DataReceiver receiver;QObject::connect(&sender, &DataSender::dataSent, &receiver, &DataReceiver::onDataReceived);sender.sendData();return 0;
}

關鍵點

  • Q_DECLARE_METATYPE:讓?QVariant?能識別自定義類型。

  • qRegisterMetaType:讓信號槽系統能處理該類型(跨線程時必須調用)。

  • QVariant::fromValue()?/?value<T>():類型與?QVariant?互轉。


2. 使用?Q_GADGET?宏(Qt 5+)

如果自定義類型是?輕量級結構體(無繼承自?QObject),可以用?Q_GADGET?宏使其支持屬性訪問和信號槽(類似?Q_OBJECT?的簡化版)。

示例

#include <QObject>// 1. 使用 Q_GADGET 聲明
struct Person {Q_GADGET  // 提供元對象能力,但不支持信號槽Q_PROPERTY(QString name MEMBER name)Q_PROPERTY(int age MEMBER age)public:QString name;int age;
};// 2. 仍然需要注冊元類型
Q_DECLARE_METATYPE(Person)// 信號槽用法與 QVariant 方式相同

適用場景

  • 需要讓結構體支持?屬性反射(如 QML 訪問)。

  • 比?QObject?更輕量,但功能有限(不能直接定義信號槽)。


3. 繼承?QObject?并作為指針傳遞

如果自定義類型繼承自?QObject,可以直接以指針形式傳遞(需注意對象生命周期管理)。

示例

#include <QObject>class Person : public QObject {Q_OBJECT
public:Person(QString name, int age) : name(name), age(age) {}QString name;int age;
};class Sender : public QObject {Q_OBJECT
public:void send() {auto person = new Person("Bob", 30);emit sendPerson(person); // 傳遞指針}
signals:void sendPerson(Person* person);
};class Receiver : public QObject {Q_OBJECT
public slots:void receivePerson(Person* person) {qDebug() << "Received:" << person->name;person->deleteLater(); // 確保內存釋放}
};

注意事項

  • 所有權管理:接收方需負責刪除對象(如?deleteLater),避免內存泄漏。

  • 適用于復雜對象,但需謹慎處理生命周期。


4. 使用共享指針(QSharedPointer?或?std::shared_ptr

如果自定義數據結構較大或需要共享所有權,可以使用智能指針。

示例

#include <QSharedPointer>struct Person {QString name;int age;
};class Sender : public QObject {Q_OBJECT
public:void send() {auto person = QSharedPointer<Person>::create("Charlie", 40);emit sendPerson(person);}
signals:void sendPerson(QSharedPointer<Person> person);
};class Receiver : public QObject {Q_OBJECT
public slots:void receivePerson(QSharedPointer<Person> person) {qDebug() << "Received:" << person->name;}
};

優點

  • 自動管理內存,避免懸垂指針。

  • 適合跨線程傳遞數據。


5. 序列化為?QByteArray(通用但低效)

將自定義類型序列化為字節流(如 JSON、二進制),通過?QByteArray?傳輸。

示例(JSON 序列化)

#include <QJsonDocument>
#include <QJsonObject>struct Person {QString name;int age;QByteArray toJson() const {QJsonObject obj;obj["name"] = name;obj["age"] = age;return QJsonDocument(obj).toJson();}static Person fromJson(QByteArray json) {auto obj = QJsonDocument::fromJson(json).object();return {obj["name"].toString(), obj["age"].toInt()};}
};// 信號槽參數使用 QByteArray

適用場景

  • 需要跨進程或網絡傳輸。

  • 數據較大時效率較低。


總結

方法優點缺點適用場景
QVariant靈活,支持元類型系統需要注冊類型通用場景(推薦)
Q_GADGET輕量級,支持屬性訪問功能有限簡單結構體 + QML 交互
QObject?指針直接傳遞對象需手動管理內存復雜對象,明確生命周期
智能指針自動內存管理需 C++11 支持共享所有權場景
序列化跨進程/網絡兼容性能較低持久化存儲或遠程通信

推薦選擇

  1. 優先用?QVariant?+?qRegisterMetaType(平衡易用性與功能)。

  2. 如果類型簡單且需 QML 訪問,用?Q_GADGET

  3. 如果對象生命周期復雜,用智能指針或?QObject?指針。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91508.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91508.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91508.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

借助于llm將pdf轉化為md文本

pdf轉化為md格式后&#xff0c;意味著非結構化文本轉為結構化文本&#xff0c;能清晰定位大標題、子標題&#xff0c;圖表。 方便后續處理&#xff0c;因為llamaindex和langchain能更有效切分md類文本&#xff0c;避免信息丟失。 1&#xff09;讀取pdf為txt 讀取pdf&#xf…

設計模式:中介者模式 Mediator

目錄前言問題解決方案結構代碼前言 中介者是一種行為設計模式&#xff0c;能讓你減少對象之間混亂無序的依賴關系。該模式會限制對象之間的直接交互&#xff0c;迫使它們通過一個中介者對象進行合作。 問題 假如你有一個創建和修改客戶資料的對話框&#xff0c; 它由各種控件…

計算機基礎速通--數據結構·線性表應用

如有問題大概率是我的理解比較片面&#xff0c;歡迎評論區或者私信指正。 考察線性表&#xff0c;核心圍繞其存儲結構特性、核心操作實現、場景應用選型三大維度&#xff0c;重點檢驗對基礎概念的理解、代碼實現能力及問題分析能力&#xff0c;通常會結合算法設計、復雜度分析和…

LeetCode Hot 100:42. 接雨水

題目 給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖&#xff0c;計算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 解析 和題目 盛水最多的容器 類似&#xff0c; LeetCode Hot 100&#xff1a;11. 盛最多水的容器-CSDN博客 只是這里將每一個柱子視為一個寬度為…

【C語言入門級教學】字符指針變量

文章目錄1.字符指針變量2. 數組指針變量2.1 數組指針變量初始化3.?維數組傳參的本質1.字符指針變量 在指針的類型中我們知道有?種指針類型為字符指針 char* ; ?般使?: int main() { char ch w; char* pc &ch;//pc的類型是char**pcw;//對pc解引用 修改ch存放的內容…

【Shell腳本自動化編寫——報警郵件,檢查磁盤,web服務檢測】

Shell腳本自動化編寫Shell腳本自動化編寫一、判斷當前磁盤剩余空間是否有20G&#xff0c;如果小于20G&#xff0c;則將報警郵件發送給管理員&#xff0c;每天檢查一次磁盤剩余空間。第一步&#xff1a;準備工作第二步&#xff1a;配置郵件信息第三步&#xff1a;檢查磁盤的自動…

Java 接口(下)

三、接口的繼承性【基礎重點】 1. Java中的接口之間的繼承關系是多繼承&#xff0c;一個接口可以有多個父接口(1) 語法&#xff1a;interface 接口名 extends 父接口1,父接口2{} 2. 類和接口之間是多實現的關系&#xff1a;一個類可以同時實現多個接口(1) 語法&#xff1a;clas…

學習游戲制作記錄(各種水晶能力以及多晶體)8.1

1.實現創建水晶并且能與水晶進行交換位置的能力創建好水晶的預制體&#xff0c;添加動畫控制器&#xff0c;傳入待機和爆炸的動畫創建Crystal_Skill_Control腳本&#xff1a;掛載在水晶預制體上private float crystalExstTime;//水晶存在時間public void SetupCrystal(float _c…

在vscode 如何運行a.nut 程序(Squirrel語言)

在 VS Code 中運行 Squirrel 語言編寫的 .nut 程序&#xff0c;需要先配置 Squirrel 運行環境并安裝相關插件&#xff0c;具體步驟如下&#xff1a; 一、安裝 Squirrel 解釋器 Squirrel 程序需要通過其官方解釋器 squirrel 或 sq 執行&#xff0c;首先需要安裝解釋器&#xf…

【數據結構】生活中的數據結構:從吃飯與編程看棧與隊列思維

生活中的數據結構&#xff1a;從吃飯與編程看棧與隊列思維 在軟件開發的世界里&#xff0c;棧&#xff08;Stack&#xff09;和隊列&#xff08;Queue&#xff09;是兩種基礎的數據結構&#xff0c;它們以不同的順序管理數據&#xff1a;棧遵循后進先出&#xff08;LIFO&#x…

牛客——接頭密匙

題目鏈接&#xff1a;牛客--接頭密匙 該題是一個很顯然的前綴樹問題&#xff0c;只需要構建a中所有數組對應的前綴樹&#xff0c;之后求b所處前綴個數即可。關于前綴樹的構建&#xff0c;可以觀看左老師算法講解045的視頻&#xff0c;簡單來講就是用特殊字符將實際數據隔開&…

【Linux基礎知識系列】第六十三篇 - 文件編輯器基礎:vim

在 Linux 系統中&#xff0c;文本編輯器是系統管理員和開發人員不可或缺的工具。vim 是一個功能強大的文本編輯器&#xff0c;廣泛應用于 Linux 系統中。它支持多種編輯模式&#xff0c;提供了豐富的文本編輯功能&#xff0c;適用于編寫代碼、配置文件和文檔。掌握 vim 的基本使…

音頻驅動的視覺特效:粒子、動畫與Shader的融合技術

音頻驅動視覺效果的實現與應用1. 引言在互動媒體、游戲和數字藝術領域&#xff0c;音頻數據實時控制視覺元素已成為核心技術&#xff0c;它能創造沉浸式體驗&#xff0c;增強用戶參與感。例如&#xff0c;音樂會可視化或VR游戲中&#xff0c;音頻信號驅動粒子流動、動畫變化和S…

機器學習環境配置

【終極指南】吃透機器學習環境配置&#xff1a;從Conda、CUDA到Docker容器化 大家好&#xff01;在機器學習的旅程中&#xff0c;一個穩定、可復現的環境是成功的基石。 第一部分&#xff1a;核心理念——為何環境配置如此重要&#xff1f; 任何機器學習模型的運行&#xff0c;…

【14】大恒相機SDK C#開發 ——Bitmap.UnlockBits()什么意思?有什么用?bmpData.Scan0;什么意思?有什么用?

文章目錄1 Bitmap.UnlockBits()2 bmpData.Scan01 Bitmap.UnlockBits() 在 C# 中&#xff0c;Bitmap.UnlockBits() 方法的作用是解鎖通過 Bitmap.LockBits() 方法鎖定的位圖數據&#xff0c;并釋放相關的位圖數據結構。 當你使用 Bitmap.LockBits() 方法鎖定位圖數據時&#x…

什么是doris

文章目錄簡介使用場景Apache Doris 主要應用于以下場景&#xff1a;實時數據分析&#xff1a;湖倉融合分析&#xff1a;半結構化數據分析&#xff1a;Apache Doris 的核心特性詳細請看官方文檔&#xff1a; Apache Doris介紹簡介 Apache Doris 是一款基于 MPP 架構的高性能、實…

python+pyside6的簡易畫板

十分簡單的一個畫板程序&#xff0c;用QLabel控件作為畫布&#xff0c;在畫布上可以畫出直線、矩形、填充矩形、園&#xff0c;橢園、隨手畫、文本等內容。將原先發布的畫板程序中的畫文本方法修改成了原位創建一編輯框&#xff0c;編輯框失去焦點后&#xff0c;即將文本畫在畫…

【數據可視化-76】從釋永信被查,探索少林寺客流量深度分析:Python + Pyecharts 炫酷大屏可視化(含完整數據和代碼)

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

WPF TreeView自帶自定義滾動條

放在TreeView.Resources中&#xff1a;<Style TargetType"ScrollBar"><Setter Property"Stylus.IsPressAndHoldEnabled" Value"false"/><Setter Property"Stylus.IsFlicksEnabled" Value"false"/><Set…

MongoDB 詳細用法與 Java 集成完整指南

MongoDB 詳細用法與 Java 集成完整指南 目錄 MongoDB 基礎概念MongoDB 安裝與配置MongoDB Shell 基本操作Java 環境準備Java MongoDB 驅動集成連接配置基本 CRUD 操作高級查詢操作索引操作聚合管道事務處理Spring Boot 集成最佳實踐 1. MongoDB 基礎概念 1.1 核心概念對比 …