1. 程式人生 > >widget,MainWindow和Dialog的選擇使用

widget,MainWindow和Dialog的選擇使用

Qt中的每個類,都有一個對應的同名標頭檔案,其中包含其類定義。例如要使用QApplication類,則需要在程式中新增" #include <QApplication>" 

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中的style都是QStyle的派生類。同一應用程式中的 widget一般都使用相同的style,然而可以呼叫QWidget::setStyle()來進行widget層次的特別設定