分類: LINUX
QApplication類用於管理應用程序範圍內的資源。其構造函數需要main函數的argc和argv作爲參數。
widget被創建時都是不可見的(always created hidden)。widget中可容納其它widget。
Qt中的widget在有用戶行爲或狀態改變時會emit signal。 signal可以和slot函數連接在一起(connect),這樣當有signal被emit時,對應的slot函數會被自動調用。
QWidget類的構造函數需要一個 QWidget * 指針作爲參數,表示其parent widget(默認值爲0,即不存在parent widget)。在parent widget被刪除時,Qt會自動刪除其所有的child widget。
Qt中有三種Layout Manager 類: QHBoxLayout,QVBoxLayOut,QGridLayOut。基本模式是將widget添加進LayOut,由Layout自動接管widget的尺寸和位置。
啓動Qt程序時可以通過 -style 參數改變程序的默認顯式風格。
Chapter 2 Creating Dialogs
2.1 Subclassing Dialog
Qt中所有dialog的基類是QDialog。QDialog派生自QWidget。
Qt中所有定義了signal或slot的類,在其類定義的開始處都要使用Q_OBJECT宏。Qt中的signal關鍵字實際上是宏定義。類似的,slots關鍵字也是宏定義。
Qt所提供的類分爲若干模塊:QtGui,QtNetWork,QtOpenGL,QtSql, QtSvg和QtXml等。
QObject::tr() 函數將輸入的字符串轉換爲其他語言(國際化)。對所有用戶可見的字符串都使用tr()函數是一個良好的習慣。
Buddy:兩個widget A和B,若A擁有快捷鍵,當用戶按下該快捷鍵時,程序的輸入焦點自動轉移到B上,則稱B是A的buddy。
QWidget::close() 是一個slot,其默認行爲是使對應的widget隱藏不可見,但並不刪除該widget。
Layout 中可包含widget和其他layout。通過嵌套使用QHBoxLayOut、QVBoxLayOut、QGridLayOut,可以構造非常複雜的dialog。值得注意的是:layout manager 類並不屬於widget。實際上,它派生自QLayout,而QLayout又派生自QObject。
QWidget::sizeHint() 返回一個widget()的理想大小(ideal size)。
emit關鍵字是Qt特有的,用於產生signal。
MOC(Meta-Object-Compiler): 對於所有使用了Q_OBJECT宏的類,在編譯時都需要通過MOC的處理,否則會出現鏈接錯誤。解決該錯誤的辦法也很簡單,重新執行qmake以更新makefile,然後重新編譯。
2.2 Signal and Slot in Depth
Signal & Slot 機制是Qt的根基。
Slot和普通的C++類成員函數幾乎完全一致;可以是virtual的,可以被重載,可以是public、protected或private的,而且也可所以被其他成員函數直接調用。
signal與slot之間的關聯可以是一對一、一對多或多對一。
signal和signal之間也可以被關聯,此種情況與signal-slot的區別在於,當第一個sigal被emit時,第二個signal也被emit。
可以調用disconnect()來解除signal 與slot之間的關聯,通常情況下很少需要顯式調用disconnect(),因爲對象被刪除時Qt會自動移除與其相關的關聯。
sigal-slot或signal-signal這樣的關聯,要求二者具備相同的參數列表;若signal比slot中的參數多,多餘的參數會被忽略。
思維定勢:signal-slot機制只能用於widget。實際上signal-slot機制是由QObject實現的,並不僅侷限於GUI編程,可以用於任何QObject子類。
2.3 Rapid Dialog Design
使用Qt Designer創建的form最終被轉換爲C++代碼。
qmake工具能夠檢測到interface file(*.ui files),並調用uic,即Qt的user interface compiler。uic將.ui文件轉換爲C++代碼,並存放在形式爲ui_xxx.h的文件中。該文件中給出了dialog對應類的完整定義,幷包含一個 setupUi()成員函數,用於初始化form。
注意,由uic創建的這個類未派生自任何Qt class。
Qt的 parent-child機制是由QObject實現的。當創建一個對象時若指定了parent,則parent將該對象添加至其 childern list。當parent被刪除時,Qt會遍歷其childern list並刪除每個child,該過程會遞歸進行。這一機制極大的簡化了內存管理,降低了內存泄露的風險——程序員只需顯式的刪除通過new創建並且沒有parent的對象。
對於widget,parent還有一層附加的意義:chidl widget 是顯示在parent widget的範圍之內的。如果刪除parent widget,不僅child widget從內存中被釋放,在屏幕上也會消失。
QDialog::accept() 將dialog的返回值設爲QDialog::Accepted(值爲1),而QDialog::reject()將返回值設爲QDIalog::Rejected(值爲0)。
2.5 Dynamic Dialogs
Dynamic Dialog指的是程序在運行時根據.ui文件創建的dialog。這樣的dialog不是通過uic將.ui轉換爲C++代碼,而是在運行時使用QUiLoader類裝載.ui文件。
可以使用QObject::findChild<T> ()來訪問form的child widget。
要使用QUiLoader,需要在Qt程序的.pro文件中添加以下內容: CONFIG += uitools
Dynamic dialog允許在不重新編譯程序的前提下更改form的佈局。
Chapter 3 Creating Main Windows
3.1 Subclassing QMainWindow
應用程序的主窗口是通過創建QMainWindow的派生類來完成的。QMainWindow和QDialog一樣,都是派生自QWidget。
closeEvent()是由QWidget提供的一個虛函數,在用戶關閉窗口時會被自動調用。
setCentralWidget()將某個Widget設置爲主窗口的central widget, 而central widget意味着在顯示時會佔據主窗口的中央位置。
Qt下的GUI 編程支持多種圖形格式。可以使用多種方式爲應用程序提供圖像,最常見的包括:
1). 將圖像存儲在文件中,運行時加載之。
2). 在源碼中include XPM文件(XPM文件也是合法的C++文件)。
3). 利用Qt的資源機制。
Qt的資源機制比之運行時加載更方便,並對所有支持的圖像格式都能良好工作。
爲了利用Qt的資源機制,需要創建一個資源文件,並在.pro文件中對應添加一行來對資源文件進行標識。例如:
RESOURCES= spreadsheet.qrc
資源文件本身採用了簡單的XML格式。它被編譯進程序的可執行文件,因此不會被丟失。在對資源進行定位時,使用路徑前綴":/",例如“ :/images/icon.png "。資源本身可以是任何類型的文件。
3.2 Creating Menus and Toolbars
Qt通過引入Action這一概念簡化了對menu和toolbar的編程。一個Action可以被添加到任意數量menu和toobar中。
在Qt中對menu和toolbar的編程涉及到三個步驟:
1). 創建並設置Action
2). 創建menu,並在其中添加Action
3). 創建toolbar,並在其中添加Action
Action的創建是通過QAction類來實現的,對每個Action,可以爲其設置accelerator,parent,shortcut key, 可見性以及status tip等屬性,並可以通過調用connect()爲ACtion設置被觸發要執行的操作。
QTableWidget的基類QAbstraceItemView提供了selectAll()這個slot。
QApplication類提供了aboutQt()這個slot,可以通過全局變量qApp(一個類型爲QApplication *的指針)來使用之。
在Qt中,menu由QMenu類的實例表示。而Qmenu是要被放入QMenuBar之中的。函數QMainWindow::menuBar()返回一個類型爲QMenuBar * 的指針。QMenuBar::addMenu()根據指定文本創建一個QMenu widget並將其添加進MenuBar中。QMenu::addAction() 則爲Menu添加Action。
任意Qt Widget都可以具備相關的一系列QAction。通過調用QWidget::addAction() ,可以爲Widget添加Action。這一特性可用來創建上下文菜單。
3.3 Setting Up the Status Bar
QMainWindow::statusBar() 返回一個指向status bar的指針;status bar 在statusBar()第一次被調用時被創建。
3.4 Implementing The Menu
QMessageBox::Defalut修飾符使得被修飾的Button成爲默認Button,而QMessage::Escape修飾符則使得Esc鍵自動觸發被修飾的Button。
QMessageBox::warning()用於彈出提示對話框。該函數屬於Qt提供的static convenicence function
static convenience function
QFileDialog::getOpenFileName() 可用於從用戶處獲得文件名——該函數彈出一個文件選擇對話框,要求用戶選擇一個文件,並返回文件名,或者在用戶選擇"Cancel"時返回空字符串。該函數的第一個參數是其parent widget。對於dialog和其他widget,parent-child關係的意味是不完全相同的。一個dialog永遠是一個獨立的窗口,但是如果它擁有parent,則默認在parent之上居中顯示。
當用戶發出關閉窗口的操作時,Qwidget::close() 這個slot會被調用,該slot向對應的widget發送close event。重新實現QWidget::closeEvent()能夠攔截這個event,以便確定是否真的要關閉窗口,防止誤操作。
每個QWidget都有一個windowModified屬性,在窗口文檔被修改時應該被設爲True,否則被設爲false。
QString::arg() 函數將字符串中編號最低的"%n"用參數進行替換,並返回替換後的字符串。
每個Action都可以擁有一個類型爲QVariant的關聯數據。
Qt中的qobject_cast<T>() 機制對於動態庫也可以正常工作。
3.5 Using Dialog
modeless window——one that runs independently of any other windows in the application
對於modeless dialog ,當其被彈出時,可能處於三種情況:
1). 這是該對話框第一次被激活
2). 該對話框之前曾被激活,但用戶又將其關閉
3). 該對話框之前曾被激活,而且仍可見
show() 將一個隱藏窗口變爲可見,而activateWIndow()則將窗口的狀態變爲active。
model window——pops up when invoked and blocks the application,preventing any other processing or interactions until it is closed.
一個dialog若是用show()來激活,則是modeless dialog;若通過exec()來激活,則是model dialog。此外,還可以調用setModel()來設置dialog的顯示模式。
QDialog::exec() 的返回至在dialog被確認時爲true,否則爲false。
在棧上創建 model dialog是一種良好的編程慣例,因爲在使用完後就不再需要,而model dialog會在作用域結束後自動被銷燬。
由於多數應用程序的About box 都是高度雷同的,Qt中提供了一個方便的static convenicence function QMessage::about(),該函數和QMessageBox::warning()很相似。
3.6 Storing Setting
Qt中是通過QSettings類來將應用程序的設置信息存儲到平臺相關的位置——windows下存入註冊表中,unix中存在文本文件中。
QSettings的構造函數包含兩個參數,分別是organization's name 和 application's name ,Qt使用這兩個參數來對應用程序的設置信息進行定位。
QSettings以key-value pair的形式存儲信息。
3.7 Multiple Documents
要想實現多文檔程序,首先必須要通過new在堆上創建主窗口,而不是在棧上創建主窗口。
QAplication::closeAllWindows() 這個slot完成的操作是關閉應用程序所有的窗口,除非其中某個窗口拒絕了close event。程序員不需要擔心未保存的修改,因爲這會由QWidget::closeEvent()負責處理。
通過在MainWindow的構造函數中調用setAttribute()函數來設置Qt::WA_DeleteOnClose屬性,可以要求Qt在窗口被關閉時將其自動銷燬
Qt在其可用所有平臺上都支持SDI和MDI程序的創建。
3.8 Splash Screnns
在Qt中爲程序添加splash screen非常簡單,可通過QSplashScreen類來實現。
通常情況下,與splash screen相關的代碼都放在main()中,出現在調用QApplication::exec()之前。
Chapter 4 Implementing Application Functionality
4.1 The Central Widget
QMainWindow的中央區域可以被任何類型的widget佔據。
4.2 Subclassing QTableWidget
QTableWidget會自動創建QTableWidgetItem來存儲用戶的輸入。
QTableWidgetItem類並不是widget,而是一個純粹的data class。
QTabeWidget::setItermProtype()可以設置在獲得用戶輸入的情況下自動創建哪種cllass。
4.3 Loading and Saving
QFile & QDataStream
QFile的析構函數負責將打開的文件關閉。
QDataStream類具有很強的通用性,可作用於QFile,QBuffer,QProcess,QTcpSocket,QUdpSocket。
Qt還提供了一個QTextStream類用於專門讀寫文本文件。
4.6 Subclassing QTableWidgetItem
每個QTableWidgetIterm中可存儲若干數據,這是通過個QVariant來實現的。每一個QVariant對象都以某個role來存儲某一類數據,常用的role有Qt::EditRole和Qt::DiaplayRole。
QVarinant對象可以存放多種類型的變量值,並提供向其他類型轉型的函數接口。
使用默認構造函數創建的QVariant對象被視爲invalid variant。
Chapter 5. Creating Custom Widgets
用戶自定義的控件可以通過繼承現有的Qt控件實現,也可以直接從QWidget繼承來實現
5.1 Customizing Qt Widgets
5.2 Subclassing QWidget
通過對QWidget進行派生,並重新編寫其部分event handler來進行繪圖和響應用戶操作,程序員可以實現對widget的外觀和行爲的完全控制。
Qt的內置Widget如QLabel、QPushButton、QTabelWidget等,就是以這種方式實現的。
宏Q_PROPERTY()用來爲widget聲明和添加自定義屬性。
每個屬性的定義都對應一個數據類型(任何被QVarinat支持的類型都可以),一個read function以及可選的write function。
對於包含自定義屬性的類,Q_OBJECT和Q_PROPERTY()這兩個宏都是必備的。
QImage類以一種硬件無關的方式存儲圖像信息。
Qt中提供了兩個類型用於存儲色彩信息:QRgb和QColor。
QRgb其實是一個typedef,用於存放32-bit的像素信息。
QColor則是一個提供了許多接口函數的類,在Qt中廣泛的用於存儲色彩。
QWidget::update()函數用於對widget進行強制性的重繪。
QWidget::updateGeometry()用於告知包含該widget的layout:該widget的size hint已發生變化,layout會自動進行調整。
通過調用QWidget::update()和QWidget::repaint(),可以強制性的產生一個 paint event,兩者的卻別在於repaint()導致立即重繪,而update()只是將一個paint event放入event queue中。
如果對update()進行連續多次調用,Qt會將連續的paint event壓縮合併爲一個paint event,以防止圖像抖動。
每個widget都擁有一個palette,用於設置widget中在什麼情況下使用什麼色彩,如背景色、文本色等。
widget的palette由三個color group組成:active ,inactive ,disabled。
QWidget::palette()以QPalette的形式返回widget的palette,而clolor group則通過枚舉類型QPalette::ColorGroup指定
5.3 Intergrating Custom Widgets with Qt Designer
要像在Qt Designer中使用自定義widget的話,必須要讓Qt Designer能夠瞭解到它們的存在。
有兩種機制:promotion approach &plugin approach
promotion approach 很容易也很省時,但缺點是自定義widget的自定義屬性在Qt Designer中是不可見和不可訪問的,而使用plugin approach時則不存在這些問題。
plugin approach要求創建一個Qt Designer 可以在運行時加載的plugin library,以用於創建widget的實例。由於Qt的MOC機制,Qt Designer可以動態獲取widget的property list。
要使用plugin approach ,首先要對QDesignCustomWidgetInterface進行派生,並重寫某些虛函數。
Q_INTERFACES()宏用於告知Qt該類實現了哪個interface。
在實現plugin class的源文件尾部,必須使用Q_EXPORT_PLUGIN2()宏使得該plugin對Qt Designer可見、可用。該宏第一個參數是plugin的名字,第二個參數是實現該plugin的class name。
5.4 Double Buffering
QWidget::style()返回用於繪製該widget時所使用的style。Qt中的s