實(shí)現(xiàn)一個簡單的地址薄,功能包括:地址的添加、瀏覽、編輯、查找、輸出文件等。

1  界面和元素

  整個地址薄界面,可視為一個 AddressBook 類。其中的 Name、Address 以及兩個編輯欄,視為 AddressBook 中的元素,也即 “包含” 關(guān)系 (has-a)。因此,可以將它們聲明為 AddressBook 的成員數(shù)據(jù)。

    平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  Name 和 Address 不涉及與用戶的交互,只顯示文本,因此,可用 QLabel 來實(shí)現(xiàn),其描述為 QLabel is used for displaying text or an imageNo user interaction functionality is provided“

  單行編輯框,可用 QLineEdit 來實(shí)現(xiàn),其描述為 ”The QLineEdit widget is a one-line text editor“

  多行編輯框,可用 QTextEdit 來實(shí)現(xiàn),其描述為 ”The QTextEdit class provides a widget that is used to edit and display both plain and rich text“

 

2  子類化 (Subclassing)

  地址薄屬于自定義窗口部件 (custom widget),在 Qt 中并沒有對應(yīng)的標(biāo)準(zhǔn)類。常用解決方法是:子類化 Qt 中的標(biāo)準(zhǔn)類。

  另外,當(dāng)一個窗口部件的功能,兼有多個標(biāo)準(zhǔn)窗口部件的功能時也常用該方法。子類化的優(yōu)點(diǎn)如下:

  1)  只需重寫基類中的虛函數(shù),來實(shí)現(xiàn)所需要的功能,體現(xiàn)了 "面向?qū)ο?quot; 的 多態(tài)性

  2)  將 UI 界面封裝在一個類中,隱藏了實(shí)現(xiàn)的細(xì)節(jié),體現(xiàn)了 “面向?qū)ο蟆?的 封裝性

  3)  實(shí)現(xiàn)的子類可被多個程序或庫調(diào)用,體現(xiàn)了設(shè)計的 可復(fù)用 原則 (reusable)

  因此,可以通過子類化 QWidget 來實(shí)現(xiàn)地址薄類 AddressBook,使用 Qt Creator 創(chuàng)建工程,會自動生成如下的代碼框架 (除綠色標(biāo)記的代碼外,其余的都是自動生成的)

2.1  Q_OBJECT 宏

  當(dāng)有 #8 的 Q_OBJECT 宏時,可簡單理解為,Qt 中允許該類使用 tr() 和 connect() 函數(shù)。

  #15 和 #16 處,聲明了兩個私有成員數(shù)據(jù),QLineEdit 型 和 QTextEdit 型指針,分別代表地址薄中的 Name 和 Address 右側(cè)的編輯框。

  那么,在析構(gòu)函數(shù) ~AddressBook() 中,是不是需要 delete 這兩個指針呢?

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 1 #include <QWidget>  // addressbook.h  2  3 class QLineEdit;
 4 class QTextEdit; 5  6 class AddressBook : public QWidget 7 { 8     Q_OBJECT 9 10 public:11     AddressBook(QWidget *parent = 0);12     ~AddressBook();13 14 private:
15     QLineEdit  *m_nameLine;
16     QTextEdit  *m_addrText;17 };

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  2.2  所有權(quán) (ownership)

  在 AddressBook 的構(gòu)造函數(shù)中,明明 new 了 QLineEdit 和 QTextEdit 型指針,但是在析構(gòu)函數(shù)中,并沒有 delete 相應(yīng)的指針,難道沒有內(nèi)存泄露么?這要從 Qt 的內(nèi)存管理說起。

  #11 構(gòu)造函數(shù)聲明中,它有一個 QWidget* 類型的參數(shù) parent,該參數(shù)會傳給其基類的構(gòu)造函數(shù) (QWidget)。這樣,當(dāng)實(shí)例化一個 AddressBook 對象時,如果為其指定了一個父類,則該父類便擁有了這個子類的 ”所有權(quán)“(ownership)。

  當(dāng)進(jìn)行資源管理時,只需要銷毀這個父類,則它所擁有的所有子類,都會被自動刪除,這是 Qt 中的一個重要概念 -- “所有權(quán)”。

  Qt 中的描述為:“The constructor of AddressBook accepts a QWidget parameter.  By convention, we pass this parameter to the base class's constructor.  This concept of ownership, where a parent can have one or more children, is useful for grouping widgets.  For example, if you delete a parent, all of its children will be deleted as well.

  具體 AddressBook 是如何獲得 m_nameLine 和 m_addrText 所有權(quán)的,會在 “3  布局管理中” 詳細(xì)闡述。

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 1 #include <QtWidgets/QLabel> 2 #include <QtWidgets/QLineEdit> 3 #include <QtWidgets/QTextEdit> 4 #include <QtWidgets/QGridLayout> 5  6 #include "addressbook.h" 7  8 AddressBook::AddressBook(QWidget *parent) 9     : QWidget(parent)10 {11     QLabel *nameLabel = new QLabel("Name:");12     m_nameLine = new QLineEdit;13     QLabel *addressLabel = new QLabel("Address:");14     m_addrText = new QTextEdit;15 16     ... ... ...17 22     setWindowTitle("Address Book");23 }24 25 AddressBook::~AddressBook()26 {27 }

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  2.3  main.cpp

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

#include "addressbook.h"#include <QApplication>int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    AddressBook w;
    w.show();    return a.exec();
}

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 

3  布局管理

  Qt 中有三個布局管理類,可以處理窗口部件的位置擺放,分別是 QHBoxLayout、QVBoxLayout 和 QGridLayout

  其中 QGridLayout 可以通過指定窗口部件的行數(shù)和列數(shù),來控制各個窗口部件的布局,如下所示:

    平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  按照上面的行數(shù)和列號,在 AddressBook 的構(gòu)造函數(shù)中,添加如下代碼:

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

     QGridLayout *layout =       layout->addWidget(nameLabel, ,      layout->addWidget(m_nameLine, ,      layout->addWidget(addressLabel, ,      layout->addWidget(m_addrText, , );

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

   Qt 中 setLayout() 函數(shù)的原型為:

void QWidget::setLayout(QLayout *layout);

  具體描述為 “Sets the layout manager for this widget to layout. The QWidget will take ownership of layout.

  通過 #21,可以將 AddressBook 的布局管理器設(shè)置為 layout, 同時 AddressBook 獲得了 layout 的擁有權(quán)。

 

參考資料: