????????第3章 Qt簡介
????????????????3.2 Qt核心模塊
????????Qt是一個大庫,由數個較小的庫或者模塊組成,最為常見的如下:core、gui、xml、sql、phonon、webkit,除了core和gui,這些模塊都需要在qmake的工程文件中啟用
????????QTextStream 流,Qdate 日期
? ? ? ? ? ? ? ? 3.3?Qt Create,用于Qt編程的集成開發環境
????????在Qt軟件開發包 (Qt Software Development Kit,SDK)中包含有Qt Creator,其中包含了Qt和快速開始使用Qt 進行開發工作的所有東西
????????可使用拖放窗體布局來完成設計的Qt設計師也完全集成到了Qt Creator中
????????Qt Creator 用到的項目文件是 qmake 的.pro 文件,通過創建或編輯Qt Creator中已有的項目文件,可以完全避免命令行工具的使用
? ? ? ? 第4章 列表
? ? ? ? 只要有可能 ,就應當使用列表而不是數組
? ? ? ? ? ? ? ? 4.1? 容器
? ? ? ? 列表 QList
????????????????4.2、迭代器
????????迭代器是一個提供對容器中的每一個元素進行間接訪問的對象,它專門被設計用于在循環之中,三種迭代器模式:foreach循環,C++迭代器,Java風格的迭代器
????????QStringList??實際上就是一個QList<QString>,使用split()函數和join()函數,在列表與字符串之間進行轉換 相當簡單
#include <QStringList>
#include <QDebug>int main()
{QString winter = "December, January, February";QString spring = "March, April, May";QStringList list;list += winter;list.append(spring);qDebug() << list;QString test = list.join(","); //list轉換字符串qDebug() << test;QStringList list2 = test.split(",");//字符串轉換listqDebug() << list2;Q_ASSERT(list2.size() == 6 );foreach (const QString &str, list2) { //foreach循環qDebug() << QString(" [%1] ").arg(str);}for(QStringList::iterator it = list2.begin();//C++迭代器it!=list2.end(); ++it){qDebug() << *it;}QListIterator<QString> itr( list2 );//Java風格的迭代器while(itr.hasNext()){qDebug() << itr.next();}return 0;
}
????????目錄(有時稱為文件夾),是文件的容器,目錄可以包含符號鏈接,指向另外的文件或目錄,對于處理文件或目錄的大多數操作,可以使用符號鏈接而不是文件名稱或路徑名稱
? ? ? ? QDir 和 QDirIterator
#include <QDebug>
#include <QDir>
#include <QDirIterator>int main()
{QDir dir = QDir::current(); // QDir 類的靜態成員函數current,成員函數 absolutePathQDirIterator qdi (dir.absolutePath(), QDir::NoDot|QDir::Files, QDirIterator::Subdirectories);while(qdi.hasNext()){ //hasNext、next 是 QDirIterator 類的成員函數qDebug() << qdi.next();}return 0;
}
????????????????4.3 關系
????????三種關系:關聯(只用于導航性)、聚合(無管理的包含關系)、組合(帶管理的包含關系)
????????第7章 庫與設計模式
????????庫是一組代碼模塊,它按照可復用的方式組織,代碼庫中保存的是有用的、可復用的、編譯后的代碼,當用#include指令包含庫模塊的頭文件時,就可以復用這個庫模塊
????????當復用來自于庫中的任何模塊時,其工作由鏈接器linker在鏈編build過程完成,可執行文件必須在運行時找到并動態地鏈接到編譯后的庫(稱為運行時庫),庫lib是一個文件,它包含一個或者多個編譯后文件,并對其進行了索引
????????C++庫能夠以多種途徑被打包:開源包?通常以壓縮的檔案文件形式發布,它包含全部的源代碼、頭文件以及鏈編腳本和文檔;dev包?在Linux包管理程序中有時被稱為-devel包,它通常以檔案文件的形式發布,包含一個庫以及相關的頭文件;運行時庫?由lib文件組成,沒有相關聯的頭文件,所以它只能用于執行已經用這個庫鏈編過的應用
? ? ? ? ? ? ? ? 7.1?建立并復用庫
????????qmake可以在工程文件里訪問CPPLIBS環境變量,其訪問語法是 $$(CPPBLIBS),qmake也可以包含其他的工程文件(片段)??????
?????????工程為 LIBS 和 INCLUDEPATH 變量?添加一些值,使它能夠找到所 依賴的庫和頭文件,qmake無法知道用來構建工程所需要的外部庫,如果工程依賴于某個外部庫,則必須編輯這個工程文件,將它的值賦予變量INCLUDEPATH和LIBS
????????假設應用所需使用dataobjects庫,其頭文件位于$CPPLIBS/dataobjects下,共享目標文件的庫位于$CPPLIBS下,那么必須如下這些行添加到工程文件中:
INCLUDEPAHT += $$(CPPLIBS)/dataobjects #頭文件
LIBS += -L$$(CPPLIBS) # lib 搜索路徑
LIBS += -ldataobjects # link with libdataobjects.so
????????組織庫:依賴性管理,對于類,只要被復用者類的接口發生改變,就使得復用者的實現必須改變,則它們之間就存在依賴性:編譯時依賴 和 鏈接時依賴,當設計類和庫時,需要確保盡可能地減少不必要的或者無意的依賴性,對于類定義頭文件,需遵循的一條規則是:如果可以使用 前置聲明,就不要使用#include指令
????????安裝庫:當編寫并測試完庫之后,在鏈編過程結束后,它將被安裝到由qmake變量DESTDIR指定的目錄下,如果要遷移庫,在windows系統中,可以將它的.dll文件復制到PATH變量中給出的合適目錄下
????????????????7.3 框架與組件
?????????在現代編程技術中,代碼復用具有最高優先級,框架是一個通用類與約定的集合,其目的是提高設計的一致性,框架一般都具有文檔豐富的公共API,API是庫中公共函數、類和接口的描述,為了實現框架,可以采取設計模式
????????Qt是許多開源的面向對象框架中的一種,它提供一組可復用的組件,用于創建跨平臺的應用?
? ? ? ? ? ? ? ? 7.4 設計模式
????????設計模式可用于許多不同場合,其中 的大多數都描述如何根據職責來區分代碼,這些模式被分成 三種 類別:創建模式、結構模式、行為模式?
????????序列化器模式:QTextStream 和 QDataStream,序列化器是一種只負責讀取或者寫入對象的對象,Qt的QTextStream序列化器用于讀寫人可讀的文件,而QDataStream序列化器用于讀寫結構化的二進制數據,這些類用?序列化模式?實現的,被用于C++和Qt中,序列化器模式的思想是將I/O代碼與類本身分開
?????????反模式:軟件設計反模式:輸入雜亂、接口膨脹、競爭風險,面向對象設計反模式:循環依賴性、“上帝”對象(具有太多信息或者太多責任的對象),編程反模式:難以編碼、魔幻數字、魔幻字符串,方法學反模式:復制--粘貼編程、一切從頭開始?
????????第8章 ?QObject,QApplication,信號和槽
????????QObject?是Qt庫中許多重要的類的基類,如QEvent,QApplication,QLayout和QWIDget,一個QObject可以有一個父對象和一些子對象,這是組合模式的另一種實現方式,它可以使用信號和槽,即觀察者模式的一種實現,與其他QObject通信
????????QObject沒有公有的復制函數或復制賦值運算符,向下到QObject類定義的結尾處有一個宏Q_DISABLE_COPY(QObject),它顯式地確保任何QObject都不能被復制,這種不帶復制構造函數策略的一個直接后果就是永遠無法通過值傳遞方式向函數傳遞QObject?
????????每個QObject都可以有(至多)一個父QObject,且可以擁有任意數量的子QObject,每個QObject都將指向各個子對象的指針存放在一個QObjectList中?
????????每個QObject父對象都會管理自己的子對象,在調用QObject的析構函數時會自動銷毀該對象的子對象,子對象列表會在各個QObject對象之間建立一種雙向的關聯:每個父對象都知道它的子對象的地址,每個子對象都知道其父對象的地址
????????給某個對象設置父對象,將會隱含地把此對象添加到父對象的子對象列表之中,重父化:把A對象設置B對象為父對象,會把A對象指針添加到B的子列表中,如果再把A對象設置C對象為父對象,A的指針會從B的子列表中刪除,然后添加到C的子列表中
????????不應將父對象和基類混為一談,父--子關系是為了描述對象運行時的約束和管理關系,基類派生關系是編譯時各個類進行判定的一種靜態關系?
????????沒有父對象的QObject應當在程序棧區中進行定義,哪些有父對象的QObject則應當在堆區動態創建出來
????????????????8.1 值和對象
????????C++類型可以分成兩類:值類型和對象類型
????????值類型的例子有:Anything*,int,char,QString,QDate 和 QVariant(QVariant是一種特殊的聯合體類型,可保存所有可復制的內置類型和編程人員定義的類型,QVariant已支持的類型:QList,QImage,QString,QMap,QHash類型),帶有公有默認構造函數、復制構造函數和復制賦值運算符的任何類都是值類型的,QObject 的設計人員毫不猶豫地采用了“無復制”策略,該方法就是將賦值運算符與復制構造函數設置為private類型
????????在棧區創建 QList、QString、QHash、QImage或者其他 與 QVariant相關類型,Qt為你完成引用計數和內存管理
????????????????8.2 組合模式:父對象和子對象
?????????復合對象是包含可以包含子對象的類,組件對象是可以擁有一個父對象的類,許多Qt類都用到了組合模式:QObject、QWIDget、QTreeWidgetItem、QDomNode、QHelpContentItem和QResource,在任何基于樹的結構體中都可以找到組合模式
????????每個QObject都可以有不限數量的QObject子對象,這些子對象的地址會存放在一個特殊的QObject指針容器內,子對象在該列表中的出現次序是它們在添加到該列表中時的次序,QObject還提供兩個名稱為findChildren()的重載(遞歸)函數,每個都會返回一個滿足特定條件的子對象列表
????????????????8.3 QApplication和事件循環
????????觀察者模式,當任意數據模型對象發生狀態改變時,就需要一種間接的方式來提醒觀察者,觀察者就是一些正在監聽狀態變化事件的對象
????????Qt的QEvent類封裝了底層事件的概念,QEvent類是若干特定的事件類的基類,QEvent對象可以由窗口系統創建以響應用戶的動作,事件循環是一個程序結構,它能夠將事件劃分優先級,排隊并分派給一些對象,事件循環通常會一直運行,直到遇到某個終止事件,QApplication::exec()函數,應用程序的這個工作部分開始于該函數的調用,終止于該函數的返回
????????事件可認為是低級消息,目標是某個特定的對象,信號可以認為是高級消息,很可能會連接到許多槽上,只有在事件循環,信號才發送到槽上,這里的信號是指對事件進行封裝的信號
????????????????8.4? Q_OBJECT?
????????QObject?支持一些普通C++對象通常所沒有的特性:信號和槽;元對象、元屬性、元方法;qobject_cast
?????????編寫C++代碼和qmake工程文件時應該遵守的一些指導原則:每個類的定義都應該放在各自對應的.h文件中;每個類的實現都應當放在相應的.cpp文件中;為避免頭文件的多次包含,頭文件應該封裝起來;每個.cpp源文件都應當列舉在工程文件的SOURCES變量中;每個頭文件都應當列舉在.pro工程文件的HEADERS變量中;Q_OBJECT宏必須出現在每個QObject派生類定義的頭文件中
????????每個Q_OBJECT宏都會產生代碼,需要使用元編譯器moc進行預處理,QObject類應該是其基類列表中的第一個基類
????????????????8.5 信號和槽
????????信號是在類定義中給出的,類似于void函數聲明的一種消息,它有參數列表卻沒有函數體,信號是一個類的接口的一部分,它看起來像函數,但不用同樣的方式進行調用---它被此類的對象發射
????????槽通常是一個void成員函數,它可以像普通的成員函數一樣進行調用,或者可以由QMetaObject系統進行間接調用?
?????????一個對象的信號可以與一個或多個對象的槽相連接,前提是這些對象存在并且參數列表從信號到槽都是賦值兼容的