程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Qt學習之路(51): QByteArray和QVariant

Qt學習之路(51): QByteArray和QVariant

編輯:關於C語言

前面我們在介紹QString的最後部分曾經提到了QByteArray這個類。現在我們就首先對這個類進行介紹。

QByteArray具有類似與QString的API。它也有相應的函數,比如left(), right(), mid()等。這些函數不僅名字和QString一樣,而且也具有幾乎相同的功能。QByteArray可以存儲原生的二進制數據和8位編碼的文本數據。這句話怎麼理解呢?我們知道,計算機內部所有的數據都是以0和1的形式存儲的。這種形式就是二進制。比如一串0、1代碼:1000,計算機並不知道它代表的是什麼,這需要由上下文決定:它可以是整數8,也可以是一個ARGB的顏色(准確的說,整數8的編碼並不是這麼簡單,但我們姑且這個理解吧)。對於文件,即便是一個文本文件,讀出時也可以按照二進制的形式讀出,這就是二進制格式。如果把這些二進制的0、1串按照編碼解釋成一個個字符,就是文本形式了。因此,QByteArray實際上是原生的二進制,但是也可以當作是文本,因此擁有文本的一些操作。但是,我們還是建議使用QString表示文本,重要的原因是,QString支持Unicode。

為了方便期間,QByteArray自動的保證“最後一個字節之後的那個位”是'\0'。這就使得QByteArray可以很容易的轉換成const char *,也就是上一章節中我們提到的那兩個函數。同樣,作為原生二進制存儲,QByteArray中間也可以存儲'\0',而不必須是'\0'在最後一位。

在有些情況下,我們希望把數據存儲在一個變量中。例如,我有一個數組,既希望存整數,又希望存浮點數,還希望存string。對於Java來說,很簡單,只要把這個數組聲明成Object[]類型的。這是什麼意思呢?實際上,這裡用到的是繼承。在Java中,int和float雖然是原生數據類型,但是它們都有分別對應一個包裝類Integer和Float。所有這些Integer、Float和String都是繼承於Object,也就是說,Integer、Float和String都是一個(也就是is-a的關系)Object,這樣,Object的數組就可以存儲不同的類型。但是,C++中沒有這樣一個Object類,原因在於,Java是單根的,而C++不是。在Java中,所有類都可以上溯到Object類,但是C++中沒有這麼一個根。那麼,怎麼實現這麼的操作呢?一種辦法是,我們都存成string類,比如int i=10,我就存"10"字符串。簡單的數據類型固然可以,可復雜一些的呢?比如一個顏色?難道要把ARGB所有的值都轉化成string?這種做法很復雜,而且失去了C++的類型檢查等好處。於是我們想另外的辦法:創建一個Object類,這是一個“很大很大的”類,裡面存儲了幾乎所有的數據類型,比如下面的代碼:

  1. class Object  
  2. {  
  3. public:  
  4.     int intValue;  
  5.     float floatValue;  
  6.     string stringValue;  
  7. }; 

這個類怎麼樣?它就足以存儲int、float和string了。嗯,這就是我們的思路,也是Qt的思路。在Qt中,這樣的類就是QVariant

QVariant可以保存很多Qt的數據類型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,並且還有C++基本類型,如int、float等。QVariant還能保存很多集合類型,如QMap<QString, QVariant>, QStringList和QList<QVariant>。item view classes,數據庫模塊和QSettings都大量使用了QVariant類,,以方便我們讀寫數據。

QVariant也可以進行嵌套存儲,例如

  1. QMap<QString, QVariant> pearMap;  
  2. pearMap["Standard"] = 1.95;  
  3. pearMap["Organic"] = 2.25;  
  4.  
  5. QMap<QString, QVariant> fruitMap;  
  6. fruitMap["Orange"] = 2.10;  
  7. fruitMap["Pineapple"] = 3.85;  
  8. fruitMap["Pear"] = pearMap; 

QVariant被用於構建Qt Meta-Object,因此是QtCore的一部分。當然,我們也可以在GUI模塊中使用,例如

  1. QIcon icon("open.png");  
  2. QVariant variant = icon;  
  3. // other function  
  4. QIcon icon = variant.value<QIcon>(); 

我們使用了value<T>()模版函數,獲取存儲在QVariant中的數據。這種函數在非GUI數據中同樣適用,但是,在非GUI模塊中,我們通常使用toInt()這樣的一系列to...()函數,如toString()等。

如果你覺得QVariant提供的存儲數據類型太少,也可以自定義QVariant的存儲類型。被QVariant存儲的數據類型需要有一個默認的構造函數和一個拷貝構造函數。為了實現這個功能,首先必須使用Q_DECLARE_METATYPE()宏。通常會將這個宏放在類的聲明所在頭文件的下面:

  1. Q_DECLARE_METATYPE(BusinessCard) 

然後我們就可以使用:

  1. BusinessCard businessCard;  
  2. QVariant variant = QVariant::fromValue(businessCard);  
  3. // ...  
  4. if (variant.canConvert<BusinessCard>()) {  
  5.     BusinessCard card = variant.value<BusinessCard>();  
  6.     // ...  

由於VC 6的編譯器限制,這些模板函數不能使用,如果你使用這個編譯器,需要使用qVariantFromValue(), qVariantValue<T>()和qVariantCanConvert<T>()這三個宏。

如果自定義數據類型重寫了<<和>>運算符,那麼就可以直接在QDataStream中使用。不過首先需要使用qRegisterMetaTypeStreamOperators<T>().宏進行注冊。這就能夠讓QSettings使用操作符對數據進行操作,例如

  1. qRegisterMetaTypeStreamOperators<BusinessCard>("BusinessCard"); 

本文出自 “豆子空間” 博客,請務必保留此出處http://devbean.blog.51cto.com/448512/276235

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved