qt序列化自定義物件 Qt之建立自定義型別

2021-10-13 06:15:25 字數 2976 閱讀 1260

摘要: 簡述 當使用qt建立使用者介面時,特別是那些帶有特殊控制和特徵的介面時,開發者通常需要建立新資料型別來擴充套件或替換qt現有的的值型別集合。 標準型別,比如:qsize、qcolor和qstring都可以被儲存到qvariant物件中,在基於qobject的類中可用作屬性的型別,並且可以在訊號-槽通訊時發射。 下面,我會建立乙個自定義型別,並且說明如何將它整合到qt的物件模型

簡述當使用qt建立使用者介面時,特別是那些帶有特殊控制和特徵的介面時,開發者通常需要建立新資料型別來擴充套件或替換qt現有的的值型別集合。

標準型別,比如:qsize、qcolor和qstring都可以被儲存到qvariant物件中,在基於qobject的類中可用作屬性的型別,並且可以在訊號-槽通訊時發射。

下面,我會建立乙個自定義型別,並且說明如何將它整合到qt的物件模型中,以便能夠以與其他qt標準型別相同的方式被儲存。接著會展示如何註冊自定義型別,使其可以在訊號槽的連線中使用。

建立乙個自定義型別

在開始之前,需要確保建立的這個自定義型別符合qmetatype的規定的所有要求。換句話說,它必須提供:

乙個公有的預設建構函式

乙個公有的拷貝建構函式

乙個公有的析構函式

下面的message類的定義包含了這些成員:

class message

public:

message();

message(const message &other);

~message();

message(const qstring &body, const qstringlist &headers);

qstring body() const;

qstringlist headers() const;

private:

qstring m_body;

qstringlist m_headers;

這個類同時還提供了乙個經常使用的建構函式,以及兩個用於獲取私有資料的共有成員函式。

使用qmetatype宣告型別

message類僅需要乙個合適的實現,以便可以使用。然而,如果沒有其他輔助資訊,qt型別系統將無法理解如何儲存、檢索和序列化該類的例項。例如:我們無法將message的值儲存到qvariant中。

qt中負責自定義型別的類是qmetatype。為了讓這個類識別該型別,當定義這個類時,需要標頭檔案中使用q_declare_metatype()巨集:

q_declare_metatype(message);

這樣,就可以將message的值儲存在qvariant物件中,並在以後讀取。完整**可參見custom type example中的示範**。

所述q_declare_metatype()巨集同時也使得這些值可以被用作訊號的引數,但是僅限於direct訊號槽連線。為了能在訊號槽機制中使用自定義型別,我們需要做一些另外的工作。

建立和銷毀自定義物件

雖然上面部分中的宣告使型別可以在direct訊號槽連線中使用,但是無法用於queued訊號槽連線中,例如:在不同執行緒的物件之間所建立的連線。這是因為元物件系統不知道如何在執行時處理自定義型別物件的建立和銷毀操作。

為了可以在執行時建立物件,需要呼叫qregistermetatype()模板函式在元物件系統中註冊此型別。只要在使用此型別的第一次連線建立前呼叫註冊函式,該型別可被用於queued訊號槽連線。

queued custom type example示例中在main.cpp檔案中宣告了乙個block類:

int main(int argc, char *ar**)

qregistermetatype();

這個型別後來在檔案window.cpp中被用於乙個訊號-槽連線:

window::window()

thread = new renderthread();

connect(thread, signal(sendblock(block)), this, slot(addblock(block)));

setwindowtitle(tr("queued custom type"));

如果乙個沒有被註冊的型別被用於queued連線中,在控制台中會輸出一條警告資訊。例如:

qobject::connect: cannot queue arguments of type 『block』 (make sure 『block』 is registered using qregistermetatype().)

使型別可列印

出於除錯目的,使乙個自定義型別可列印是非常有用的,就像下面的**一樣:

message message(body, headers);

qdebug() << "original:" << message;

可以通過為此型別建立流操作符來達到目的,這通常定義在該型別的標頭檔案中:

qdebug operator<

在custom type example的message類實現中,我們努力讓可列印的內容盡可能的通俗易讀:

qdebug operator<

const qstring body = message.body();

qvector pieces = body.splitref("\r\n", qstring::skipemptyparts);

if (pieces.isempty())

dbg.nospace() << "message()";

else if (pieces.size() == 1)

dbg.nospace() << "message(" << pieces.first() << ")";

else

dbg.nospace() << "message(" << pieces.first() << " ...)";

return dbg.maybespace();

當然,輸出到debug流的資訊是簡單還是複雜都隨你的意思。需要注意的是這個函式的返回值是qdebug物件本身,儘管它通常通過呼叫qdebug的成員函式maybespace()來獲得,用空白字元填充流,以使其更具可讀性。

**:

qt序列化自定義物件 Qt序列化

class painting public painting painting const qstring title,const qstring artist,int year qstring title const private qstring mytitle qstring myartist...

自定義序列化物件

很多時候,我們需要將物件序列化成字串儲存到記憶體 磁碟或者 page.viewstate 中。基於種種原因,我們希望序列化結果盡可能小,盡可能簡單,即便用其他的方法 比如正規表示式 也能解析出資料。binaryformatter 的結果轉換成字串 或者base64 長度太大,而 xmlseriali...

可序列化和自定義序列化

序列化技術的主要兩個目的是 持久化儲存 按值封送。net framework支援三種序列化器 binary xml soap.他們各有優缺點,分別列如下 1.binary序列化是完全保真的,因為除非特殊宣告為nonserialized,那麼所有成員 包括私有的和公有的 都會被序列化。該序列化器的結果...