首页 > 其他 > 详细

Qt 地址薄 (一) 界面设计

时间:2017-01-20 14:32:27      阅读:223      评论:0      收藏:0      [点我收藏+]

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

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“

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

  Address 右侧的多行编辑框,可用 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_nameLinem_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 地址薄 (一) 界面设计

原文:http://www.cnblogs.com/xinxue/p/6305951.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!