广州C/C++培训
达内广州岗顶中心

18087159764

热门课程

Qt地址薄的界面设计

  • 时间:2017-01-22
  • 发布:广州C++培训
  • 来源:达内新闻

广州C++培训机构的老师这一期给大家讲Qt地址薄的界面设计。

实现一个简单的地址薄,功能包括:地址的添加、浏览、编辑、查找、输出文件等。

1 界面和元素

整个地址薄界面,可视为一个AddressBook类。其中的Name、Address以及两个编辑栏,视为AddressBook中的元素,也即“包含”关系(has-a)。因此,可以将它们声明为AddressBook的成员数据。

Name和Address不涉及与用户的交互,只显示文本,因此,可用QLabel来实现,其描述为”QLabel is used for displaying text or an image. No user interaction functionality is provided“

单行编辑框,可用QLineEdit来实现,其描述为”The QLineEdit widget is a one-line text editor“

多行编辑框,可用QTextEdit来实现,其描述为”The QTextEdit class provides a widget that is used to edit and display both plain and rich text“

2 子类化(Subclassing)

地址薄属于自定义窗口部件(custom widget),在Qt中并没有对应的标准类。常用解决方法是:子类化Qt中的标准类。

另外,当一个窗口部件的功能,兼有多个标准窗口部件的功能时,也常用该方法。子类化的优点如下:

1) 只需重写基类中的虚函数,来实现所需要的功能,体现了"面向对象"的多态性

2) 将UI界面封装在一个类中,隐藏了实现的细节,体现了“面向对象”的封装性

3) 实现的子类可被多个程序或库调用,体现了设计的可复用原则(reusable)

因此,可以通过子类化QWidget来实现地址薄类AddressBook,使用Qt Creator创建工程,会自动生成如下的代码框架(除绿色标记的代码外,其余的都是自动生成的)

2.1 Q_OBJECT宏

当有#8的Q_OBJECT宏时,可简单理解为,Qt中允许该类使用tr()和connect()函数。

#15和#16处,声明了两个私有成员函数,QLineEdit型和QTextEdit型指针,分别代表地址薄中的Name和Address右侧的编辑框。

那么,在析构函数~AddressBook()中,是不是需要delete这两个指针呢?

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 };

2.2 所有权(ownership)

在AddressBook的构造函数中,明明new了QLineEdit和QTextEdit型指针,但是在析构函数中,并没有delete相应的指针,难道没有内存泄露么?这要从Qt的内存管理说起。

#11构造函数声明中,它有一个QWidget*类型的参数parent,该参数会传给其基类的构造函数(QWidget)。这样,当实例化一个AddressBook对象时,如果为其指定了一个父类,则该父类便拥有了这个子类的”所有权“(ownership)。

当进行资源管理时,只需要销毁这个父类,则它所拥有的所有子类,都会被自动删除,这是Qt中的一个重要概念--“所有权”。

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所有权的,会在“3 布局管理中”详细阐述。

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 }

2.3 main.cpp

#include "addressbook.h"

#include <QApplication>

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

AddressBook w;

w.show();

return a.exec();

}

3 布局管理

Qt中有三个布局管理类,可以处理窗口部件的位置摆放,分别是QHBoxLayout、QVBoxLayout和QGridLayout

其中QGridLayout可以通过指定窗口部件的行数和列数,来控制各个窗口部件的布局,如下所示:

按照上面的行数和列号,在AddressBook的构造函数中,添加如下代码:

16    QGridLayout *layout = new QGridLayout;

17

18    layout->addWidget(nameLabel, 0, 0);

19    layout->addWidget(m_nameLine, 0, 1);

20    layout->addWidget(addressLabel, 1, 0, Qt::AlignTop);

21    layout->addWidget(m_addrText, 1, 1);

21    setLayout(layout);

Qt中setLayout()函数的原型为:

void QWidget::setLayout(QLayout *layout);

具体描述为“Sets the layout manager for this widget to layout. The QWidget will take ownership of layout.”

通过#21,可以将AddressBook的布局管理器设置为layout,同时AddressBook获得了layout的拥有权。Qt地址薄(一)界面设计

实现一个简单的地址薄,功能包括:地址的添加、浏览、编辑、查找、输出文件等。

1 界面和元素

整个地址薄界面,可视为一个AddressBook类。其中的Name、Address以及两个编辑栏,视为AddressBook中的元素,也即“包含”关系(has-a)。因此,可以将它们声明为AddressBook的成员数据。

Name和Address不涉及与用户的交互,只显示文本,因此,可用QLabel来实现,其描述为”QLabel is used for displaying text or an image. No user interaction functionality is provided“

单行编辑框,可用QLineEdit来实现,其描述为”The QLineEdit widget is a one-line text editor“

多行编辑框,可用QTextEdit来实现,其描述为”The QTextEdit class provides a widget that is used to edit and display both plain and rich text“

2 子类化(Subclassing)

地址薄属于自定义窗口部件(custom widget),在Qt中并没有对应的标准类。常用解决方法是:子类化Qt中的标准类。

另外,当一个窗口部件的功能,兼有多个标准窗口部件的功能时,也常用该方法。子类化的优点如下:

1) 只需重写基类中的虚函数,来实现所需要的功能,体现了"面向对象"的多态性

2) 将UI界面封装在一个类中,隐藏了实现的细节,体现了“面向对象”的封装性

3) 实现的子类可被多个程序或库调用,体现了设计的可复用原则(reusable)

因此,可以通过子类化QWidget来实现地址薄类AddressBook,使用Qt Creator创建工程,会自动生成如下的代码框架(除绿色标记的代码外,其余的都是自动生成的)

2.1 Q_OBJECT宏

当有#8的Q_OBJECT宏时,可简单理解为,Qt中允许该类使用tr()和connect()函数。

#15和#16处,声明了两个私有成员函数,QLineEdit型和QTextEdit型指针,分别代表地址薄中的Name和Address右侧的编辑框。

那么,在析构函数~AddressBook()中,是不是需要delete这两个指针呢?

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 };

2.2 所有权(ownership)

在AddressBook的构造函数中,明明new了QLineEdit和QTextEdit型指针,但是在析构函数中,并没有delete相应的指针,难道没有内存泄露么?这要从Qt的内存管理说起。

#11构造函数声明中,它有一个QWidget*类型的参数parent,该参数会传给其基类的构造函数(QWidget)。这样,当实例化一个AddressBook对象时,如果为其指定了一个父类,则该父类便拥有了这个子类的”所有权“(ownership)。

当进行资源管理时,只需要销毁这个父类,则它所拥有的所有子类,都会被自动删除,这是Qt中的一个重要概念--“所有权”。

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所有权的,会在“3 布局管理中”详细阐述。

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 }

2.3 main.cpp

#include "addressbook.h"

#include <QApplication>

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

AddressBook w;

w.show();

return a.exec();

}

3 布局管理

Qt中有三个布局管理类,可以处理窗口部件的位置摆放,分别是QHBoxLayout、QVBoxLayout和QGridLayout

其中QGridLayout可以通过指定窗口部件的行数和列数,来控制各个窗口部件的布局,如下所示:

按照上面的行数和列号,在AddressBook的构造函数中,添加如下代码:

16    QGridLayout *layout = new QGridLayout;

17

18    layout->addWidget(nameLabel, 0, 0);

19    layout->addWidget(m_nameLine, 0, 1);

20    layout->addWidget(addressLabel, 1, 0, Qt::AlignTop);

21    layout->addWidget(m_addrText, 1, 1);

21    setLayout(layout);

Qt中setLayout()函数的原型为:

void QWidget::setLayout(QLayout *layout);

具体描述为“Sets the layout manager for this widget to layout. The QWidget will take ownership of layout.”

通过#21,可以将AddressBook的布局管理器设置为layout,同时AddressBook获得了layout的拥有权。

上一篇:GCC与G++的区别
下一篇:【广州C++培训机构】洛谷P1177快速排序

iPhone 8又贵又抢手!【广州达内】

学习C++必须要先学习C语言吗?

哪里有软件培训班?达内带你看iPhone8/7s大亮点!

达内培训怎么样?看Python功能与特点的讲解!

选择城市和中心
贵州省

广西省

海南省

台湾