The Book of QT4 翻译:1.2 布局,对象层级和内存管理

来源:互联网 发布:剑灵捏脸数据图导入 编辑:程序博客网 时间:2024/04/29 06:09

The Book of QT4 翻译:1.2 布局,对象层级和内存管理

作者:mcxiaoke  来源:博客园  发布时间:2010-05-12 10:57  阅读:651 次  原文链接   [收藏]  

The Book of QT4 翻译

QT程序设计艺术

---------------------------------------------------------------------------------

原名:The Book of QT 4:The Art of Building Qt Applications

译名:The Book of QT 4中文版:QT程序设计艺术

---------------------------------------------------------------------------------

第一章 基础,工具和第一行代码


*******************************************************************
******************* 1.2 布局,对象层级和内存管理 *************************
*******************************************************************

 

1.2.1 如何自动布置窗口部件(也可以叫控件)


为了扩展我们第一节的HelloWorld程序使它不仅仅是显示一个文本标签,而是像图1.2那样按顺序显示两个QLabel,我们使用QT的布局系统。这个系统自动安排GUI元素:包括窗口小部件和控件。类似于在印刷领域中的术语,我们称之为布局。


图1.2显示的界面的源代码如下:

 

代码

 

 

除了1.1节中我们已经使用过的QApplication和QLabel,我们现在还要包含另外一个用来垂直排列小部件的类:QVBoxLayout,名字中的V代表垂直(vertical)。这一次我们使用QWidget对象作为应用程序的主窗口,而不是上一节的QLabel对象。使用这个名字仅仅是出于习惯。只需要两步,QWidget对象就可以成为一个独立的窗口。第一步,调用QWidget对象的构造器,如果像在本例中一样没有提供参数,新对象就没有父窗口,因此,处于对象继承层次的最顶层。第二步,小部件只有调用show()方法显示出来时才能成为一个窗口。

创建完QWidget后,我们创建了一个QVBoxLayout对象。我们在这里使用new操作符代替:
QVBoxLayout mainLayout(&window);

具体将在下面的1.2.2节中解释。因此,新创建的QVBoxLayout知道这表示window窗口的布局,QWidget对象的指针作为一个参数传给了它的构造器。

类似地,我们还创建了One和Two两个文本标签对象。为了使他们接受窗口布局对象的管理,我们通过QVBoxLayout对象的addWidget()方法将它们添加到布局中。


这个程序除此之外的部分与我们的第一个例子几乎没有区别。注意到我们仅仅调用了show()方法使得QWidget对象可见,这将使得QWidget包含的所有窗口部件都显示在屏幕上,在本例中就是那两个标签。

最后,我们像以前一样开始了事件循环,而且通过事件循环传回来一个返回值作为应用程序的返回值。简单的返回0将立即结束程序并且不再显示窗口。

这个程序显示了使用布局管理的主要优点:你不必关注窗口部件的确切位置。另外,用户可以缩放布局窗口,布局管理器将自动的调整窗口组件,确保他们合理的填充可用空间,而不需要开发者写详细的代码来实现。

布局管理也允许开发者自定义单个部件的行为:例如,当一个控件应该占满尽可能多的空间,或者需要限制大小时,又或者处理不需要太多垂直空间的部件,如CheckBox时。第五章详细介绍了如何实现这样的布局。

 

1.2.2 对象层次的内存管理

 

图1.2展示的应用程不仅在自动布局方面异于第一节的HelloWorld程序,在其它方面也有显著的不同。变量声明QWidget window用于分配内存给QWidget对象,但给QVBoxLayout和QLabel对象时,我们使用了new操作符,使用:
QVBoxLayout* mainLayout = new QVBoxLayout(&window);
而不是:
QVBoxLayout mainLayout(&window);
创建布局对象。

我们详述这个是因为C++不提供自动内存管理。一般来说,程序员必须自己小心处理。然而,正如下面提到的,QT接管了部分的内存管理工作。所有的类对象都继承自QObject形成了一个树形结构:对象可以拥有子对象。如果一个对象删除了,QT自动删除它所有的子对象,以及子对象的后代。

                    QWidget
|                          |                 |
QVBoxLayout    QLabel      QLabel

 

从另一方面说,如果对象树的根节点消失了,QT会自动删除整个树。这缓解了程序员跟踪对象后代和释放它们占用的内存的负担。然而,为了使自动内存管理生效,所有的后代(以及后代的后代)都必须分配在堆(Heap)上,即必须使用new操作符创建它们。使用new操作符创建的对象都引用了一个指向堆的指针。这就是为什么mainLayout被声明为一个指向QVBoxLayout的指针,而不是一个QVBoxLayout对象。

不在堆上创建对象(即不使用new分配内存)是一个初学者的常见误区:窗口部件只被创建在栈(Stack)上,(例如,在一个类的构造器中),当进程结束时他们被编译器删除。虽然应用程序并不仅是简单的产生部件,但它们对于人来说,永远是不可见的。

而且,这个声明不仅仅创建了一个QVBoxLayout对象,也使它成为Qwidget对象窗口的子对象,通过QVBoxLayout类的构造器实现。与此相反,两个QLabel对象初始化的时候没有父对象,QLabel构造器仅仅初始化了标签的文本:
QLabel* label1 = new QLabel("One");

我们随后使用QVBoxLayout::addWidget()方法确保QWidget对象承担作为每个新标签父对象的责任。(事实上,一个窗口部件包含的GUI元素必须成为该对象的子对象。由此,QWidget对象成为QLabel对象的父对象,而不是我们可能以为的QVBoxLayout对象的子对象。)图1.3展示的树结构的创建过程就是这样的。

窗口对象的子对象,布局对象和两个标签都必须使用new操作符在堆上创建从另一方面说,我们使用QWidget window;在栈上创建了窗口.因此当应用程序关闭时我们不必手动删除它。(只有当对象没有父对象是你才可以这样做。)因而,在多数情况下,你应该使用new操作符创建继承自QObject的类对象。

 

1.2.3 其它布局类型

 

QHBoxLayout类用来水平布局元素,和用来垂直布局元素的QVBoxLayout类一样,它的界面也类似于QVBoxLayout。如果你用QHBoxLayout替换掉例子中的QVBoxLayout,图1.2将会显示成如下图所示:

这里还有一个使用QGridLayout网格布局的例子:

 

代码

 

 

这个程序和前一个例子差不多,只不过用QGridLayout取代了QVBoxLayout作为容器,这次包含了六个QLabel对象。与水平或垂直布局类的addWidget()方法不同的是,QGridLayout::addWidget()方法需要三个参数:要被指派的部件,以及该部件放置在在网格中的行和列的位置。网格的第一个格子的坐标是(0,0),位于左上角。结果如图1.5所示:

如果文本Five无法正确显示,可能的原因是源文件是以UTF-8编码格式保存的。你需要转换为ISO-8859-1或者 ISO-8859-15格式。在KDE的编辑器Kate中,这个选项可以在另存为对话框中看到。(Windows系统中也是类似的。)

你将在第五章中了解到关于布局管理的更多细节。我将介绍如何设计复杂的布局,例如通过嵌套布局。还将介绍手动布局,分裂器(Splitters)和QStackedLayout类。

分裂器的行为类似于水平布局和垂直布局,但是在额外的空白空间里显示被称之为手柄(handle)的东西。用户可以直接拖动手柄使对面的部件获得根多的空间。当拖动一个手柄时,窗口部件朝手柄拖动的方向收缩。

另一方面,QStackedLayout类管理一些面板,这些面板每个都可以包含多组部件,但只有一个可以显示。设置对话框可以使用这个类,例如,当用户选择这样一个设置对话框左边面板的一个目录时,右边的面板显示用来更改所选目录选项的窗口部件。当用户更改左边的目录时,QStackedLayout对象知道应该改在右边显示一个不同的页面。

 


出处:http://mcxiaoke.cnblogs.com/ 
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名(包含链接).

原创粉丝点击