zoukankan      html  css  js  c++  java
  • Qt 地址薄 (一) 界面设计

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

    1  界面和元素

      整个地址薄界面,为 AddressBook 类。其中的两个文本框和两个编辑栏,与 AddressBook 是 “包含” 关系 (has-a),故可将它们声明为类成员数据。

       

    1) 文本框

        Name 和 Address 只 显示文本,可用 QLabel 实现,Qt 中其描述为 ”QLabel is used for displaying text or an image. No user interaction functionality is provided“

    2) 单行编辑框

        用 QLineEdit 实现,其描述为 ”The QLineEdit widget is a one-line text editor“

    3) 多行编辑框

        用 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

    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 #include <QLineEdit>
     4 #include <QTextEdit>
     5 
     6 class AddressBook : public QWidget
     7 {
     8     Q_OBJECT
     9 
    10 public:
    11     AddressBook(QWidget *parent = nullptr);
    12     ~AddressBook();
    13 
    14 private:
    15     QLineEdit  *name_line_;
    16     QTextEdit  *addr_text_;
    17 };

      2.2  所有权 (ownership)

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

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

    这个子类的 “所有权”。当进行资源管理时,只需要销毁这个父类,则它所拥有的所有子类,都会被自动删除,这是 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 是如何获得 name_line_addr_text_ 所有权的,会在 “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 *name_label = new QLabel("Name:");
    12     name_line = new QLineEdit;
    13     QLabel *addr_label = new QLabel("Address:");
    14     addr_text = new QTextEdit;
    15 
    16     ... ... ...
    17 
    22     setWindowTitle("Address Book");
    23 }
    24 
    25 AddressBook::~AddressBook()
    26 {
    27 }

    3  布局管理

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

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

       

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

    16     QGridLayout *layout = new QGridLayout;
    17 
    18     layout->addWidget(name_label, 0, 0);
    19     layout->addWidget(name_line_, 0, 1);
    20     layout->addWidget(addr_label, 1, 0, Qt::AlignTop);
    21     layout->addWidget(addr_text_, 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 5.9 | Qt Widgets | Part 1 - Designing the User Interface

     

  • 相关阅读:
    oracle 使用toad界面创建DBLINK
    oracle 批量修改
    blast原理
    Masked genomes/sequence
    HSP
    gapped alignment
    genBlastA
    用blastall进行序列比对
    formatdb
    download文件转为可执行格式
  • 原文地址:https://www.cnblogs.com/xinxue/p/6305951.html
Copyright © 2011-2022 走看看