布局管理
来源:互联网 发布:2017年mac游戏推荐 编辑:程序博客网 时间:2024/05/18 06:22
布局管理
以下是Qt手册中的《布局管理》的译文
在一个Widget中,Qt布局管理系统提供了一个简单而有效的方式来自动组织子widget,以保证他们能够很好地利用可用空间。
介绍
Qt包含一个布局管理类的集合,它们被用来描述widgets如何在应用程序的用户界面中呈现的。当可用空间发生变化时,这些布局将自动调整widgets的位置和大小,以确保它们布局的一致性和用户界面主体可用。
所有QWidget的子类都可以用布局来管理它们的子类。QWidget::setLayout()函数给widget提供一个布局。当布局通过这种方式设置到widget,它将负责以下任务:
l 子widget的定位
l 窗口的合理默认空间
l 窗口的合理最小空间
l 调整大小处理
l 当内容发生变化时自动调整
n 字体、大小或者内容变化
n 显示或 隐藏widget
n 移除子widget
Qt的布局类
QGraphicsAnchorLayout
Layout where one can anchor widgets together in Graphics View
在制图视图中布局widget
QGraphicsAnchor
Represents an anchor between two items in a QGraphicsAnchorLayout
?
QBoxLayout
Lines up child widgets horizontally or vertically
水平或垂直整理子widget
QHBoxLayout
Lines up widgets horizontally
水平整理子控件
QVBoxLayout
Lines up widgets vertically
垂直整理子控件
QFormLayout
Manages forms of input widgets and their associated labels
label-inputwidget模式表单布局
QGridLayout
Lays out widgets in a grid
网格布局
QLayout
The base class of geometry managers
布局,几何管理的基类
QLayoutItem
Abstract item that a QLayout manipulates
管理的抽象元素
QSpacerItem
Blank space in a layout
空白区域布局
QWidgetItem
Layout item that represents a widget
布局元素
QSizePolicy
Layout attribute describing horizontal and vertical resizing policy
大小策略
QStackedLayout
Stack of widgets where only one widget is visible at a time
栈模式布局,一次只显示一个
QButtonGroup
Container to organize groups of button widgets
管理按钮的容器
QGroupBox
Group box frame with a title
带标题的组箱框架
QStackedWidget
Stack of widgets where only one widget is visible at a time
栈模式的widget,一次只显示一个
水平、垂直、网格和表格布局
给widgets一个很好布局的最好方式是使用内置的布局管理器: QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout. 这些类都从QLayout继承而来,它们都来源于QObject(而不是QWidget)。创建更加复杂的布局,可以让它们彼此嵌套完成。
l QHBoxLayout是水平布局,将从左往右(or right to left for right-to-left languages )widget布局成水平行
l QVBoxLayout是垂直布局,从顶部到底部
l QGridLayout 是二位的网格布局。它可以容纳多个单元格:
l QFormLayout是两列label-field式的表单布局
代码举例
下面代码创建QHBoxLayout来管理5个QPushButtons的几何图形:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->show();
QGridLayout示例如下:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");
QGridLayout *layout = new QGridLayout;
layout->addWidget(button1, 0, 0);
layout->addWidget(button2, 0, 1);
layout->addWidget(button3, 1, 0, 1, 2);
layout->addWidget(button4, 2, 0);
layout->addWidget(button5, 2, 1);
window->setLayout(layout);
window->show();
QFormLayout示例如下:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QLineEdit *lineEdit1 = new QLineEdit();
QPushButton *button2 = new QPushButton("Two");
QLineEdit *lineEdit2 = new QLineEdit();
QPushButton *button3 = new QPushButton("Three");
QLineEdit *lineEdit3 = new QLineEdit();
QFormLayout *layout = new QFormLayout;
layout->addRow(button1, lineEdit1);
layout->addRow(button2, lineEdit2);
layout->addRow(button3, lineEdit3);
window->setLayout(layout);
window->show();
布局技巧
当使用布局的时候,在创建子widget时,没必要给它传递父类。布局会自动重新定义它们的父类(通过QWidget::setParent())以确保它们是装载布局的widget的子类。
注意1:布局中的控件是装载布局控件的子控件,不是布局的子控件。控件只能以其他控件作为父类,不可以以布局作为父类。在布局上,可以使用addLayout来嵌套布局;被嵌套的布局,将变成上层布局的子布局。
向布局添加widgets
添加布局到widgets时,布局过程执行如下:
1. 所有widgets将根据它们的 QWidget::sizePolicy() and QWidget::sizeHint()首先分配一些空间。
2. 如果有widgets设置了大于0的拉伸系数,接下来它们将按照拉伸系数的比例来分配空间。
3. 如果有widgets设置的拉伸系数是0,它将在没有其他widgets需要空间时获取更多空间。其中,带Expanding大小策略的widget将首先获得空间。
4. 所有分配了小于最小空间(或者设置了最小的size hint)的widget将按要求分配最小空间。(在拉伸系数成为决定因子时,widgets没必要再用最小值或者最小hint)。
5. 任何分配了大于最大空间的widget将按要求分配最大空间。(拉伸系数起着决定作用)
拉伸系数
通常,widgets创建的时候没有设置拉伸系数。当widget整理到一个布局中时,它们将根据QWidget::sizePolicy()或者最小大小hint(取决于谁更大)分配一定空间。拉伸系数被用于按比例改变widget的分配空间。
如果3个widget用QHBoxLayout 来布局,不带拉伸系数,它们将得到像下面的布局:
如果带上拉伸系数,情况将变成这样:
自定义widget的布局
当编写自定义widget类时,需要显示提供它的布局属性。如果widget有Qt自带的布局,它能够自己满足自己。如果没有任何子布局,或者使用手动布局,可以通过下面的机制来改变widget的行为:
l 实现QWidget::sizeHint() 来返回首先大小
l 实现QWidget::minimumSizeHint()来返回widget可以拥有的最小空间
l 调用QWidget::setSizePolicy来描述widget所需的空间
当size hint、minimum size或size policy改变时,调用QWidget::updateGeometry()。这将促使布局重新进行计算。连续多次调用QWidget::updateGeometry()只会发生一次布局重新计算。
即便实现了QWidget::heightForWidth(),也有必要提供合理的sizeHint()。
进一步了解,参见:Trading Height for Width.
布局问题
The use of rich text in a label widget can introduce some problems to the layout of its parent widget. Problems occur due to the way rich text is handled by Qt's layout managers when the label is word wrapped.
In certain cases the parent layout is put into QLayout::FreeResize mode, meaning that it will not adapt the layout of its contents to fit inside small sized windows, or even prevent the user from making the window too small to be usable. This can be overcome by subclassing the problematic widgets, and implementing suitable sizeHint() andminimumSizeHint() functions.
In some cases, it is relevant when a layout is added to a widget. When you set the widget of a QDockWidget or a QScrollArea (withQDockWidget::setWidget() andQScrollArea::setWidget()), the layout must already have been set on the widget. If not, the widget will not be visible.
在QLabel中使用富文本会给布局的父类widget带来一些问题。问题发生的原因是因为当label被文字环绕时,富文本被Qt的布局管理器控制。
在某些情况下,父类布局被放入QLayout::FreeResize模式,这意味着它将不适应内容布局所设置的最小窗口,或者甚至阻止用户让窗口小到不可用的情况。这个可以通过将问题控件作为子类来解决,并实现合适的sizeHint()和minimumSizeHint()函数。
在一些情况下,当布局被添加到widget时需要特别注意。当设置QDockWidget or a QScrollArea widget时(用QDockWidget::setWidget() andQScrollArea::setWidget()),布局必须已经被设置到widget上。否则,这些widget将不可见。
手动布局
如果想自定义一个独特的布局,可以按 如上所述地自定义一个widget。实现QWidget::resizeEvent()来计算所需的大小分配并在每个子类中调用setGeometry() 。
需要布局需要重新计算大小时,widget将提供一个事件接口QEvent::LayoutRequest 。实现QWidget::event()来接收QEvent::LayoutRequest事件。
自定义布局管理
自定义布局的唯一方法是继承QLayout来完成自己布局管理器。Border Layout 和Flow Layout 例子将说明如何来完成。
下面将举个例子来说明。CardLayout 类,受同名java布局管理的启发。它分层管理每个元素,每个元素的通过QLayout::spacing()来设置位移量。
编写自定义布局类,必须定义以下内容:
l 由布局控制的存放元素的数据结构。每个元素都是一个QLayoutItem。在这个例子中,我们将使用QList 。
l addItem(),描述如何添加元素到布局。
l setGeometry(),描述如何完成布局
l sizeHint(),布局的首选大小
l itemAt(),描述如何递归布局
l takeAt(),描述如何移除布局中的元素。
在大多数情况下,还需要实现minimumSize()。
头文件
card.h
#ifndef CARD_H
#define CARD_H
#include <QtGui>
#include <QList>
class CardLayout : public QLayout
{
public:
CardLayout(QWidget *parent, int dist): QLayout(parent, 0, dist) {}
CardLayout(QLayout *parent, int dist): QLayout(parent, dist) {}
CardLayout(int dist): QLayout(dist) {}
~CardLayout();
void addItem(QLayoutItem *item);
QSize sizeHint() const;
QSize minimumSize() const;
int count() const;
QLayoutItem *itemAt(int) const;
QLayoutItem *takeAt(int);
void setGeometry(const QRect &rect);
private:
QList<QLayoutItem*> list;
};
#endif
实现文件
card.cpp
#include "card.h"
int CardLayout::count() const
{
// QList::size() returns the number of QLayoutItems in the list
return list.size();
}
int CardLayout::count() const
{
// QList::size() returns the number of QLayoutItems in the list
return list.size();
}
int CardLayout::count() const
{
// QList::size() returns the number of QLayoutItems in the list
return list.size();
}
CardLayout::~CardLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
void CardLayout::setGeometry(const QRect &r)
{
QLayout::setGeometry(r);
if (list.size() == 0)
return;
int w = r.width() - (list.count() - 1) * spacing();
int h = r.height() - (list.count() - 1) * spacing();
int i = 0;
while (i < list.size()) {
QLayoutItem *o = list.at(i);
QRect geom(r.x() + i * spacing(), r.y() + i * spacing(), w, h);
o->setGeometry(geom);
++i;
}
}
QSize CardLayout::sizeHint() const
{
QSize s(0,0);
int n = list.count();
if (n > 0)
s = QSize(100,70); //start with a nice default size
int i = 0;
while (i < n) {
QLayoutItem *o = list.at(i);
s = s.expandedTo(o->sizeHint());
++i;
}
return s + n*QSize(spacing(), spacing());
}
QSize CardLayout::minimumSize() const
{
QSize s(0,0);
int n = list.count();
int i = 0;
while (i < n) {
QLayoutItem *o = list.at(i);
s = s.expandedTo(o->minimumSize());
++i;
}
return s + n*QSize(spacing(), spacing());
}
进一步说明
自定义布局没有控制宽和高。
忽略了 QLayoutItem::isEmpty(),这意味着布局将把隐藏widget作为可见的。
对于复杂布局,通过缓存计算将大大提高速度。在那种情况下,实现QLayoutItem::invalidate() 来标记数据是脏数据。
调用QLayoutItem::sizeHint()等的代价比较大。在通过函数中,需要再次使用,最好将结果保存在本地变量中。
在同样函数的同一个元素中,不应该调用两次 QLayoutItem::setGeometry()。 这个调用将耗费巨大,如果它用几个子widget,因为布局管理器每次都要做一个完整的布局。替代方法:先计算geometry,然后再设置(这种事情,不仅应该在布局时注意,在实现resizeEvent()时也需要按同样方法来做)。
参考
1. Qt手册《Layout Management》
窗体小部件和布局
窗体小部件
窗体小部件(Widgets)是Qt中创建用户界面的主要元素。窗体小部件可以显示数据和状态信息,接受用户输入,和提供组织其他窗体小部件的容器。
没有嵌入到父级窗体小部件的部件被称为窗口(window)。
布局
布局是一个种高雅而灵活的方式来自动把子类窗体小部件组织到它们的容器中。每个窗体小部件通过sizeHint和sizePolicy属性向布局提供大小需求,布局根据可用空间进行分配。
窗体小部件的样式
样式(styles)绘制窗体小部件,并封装了GUI的外观和感觉。Qt的内置窗体小部件使用QStyle类完成几乎所有的绘制工作,以确保它们看来确实是一致的、本地窗体小部件。
QSS(Qt Style Sheets)允许自定义窗体小部件的外观。
窗体小部件的类
Qt Widget Gallery
基础部件
QCheckBox
Checkbox with a text label
QComboBox
Combined button and popup list
QCommandLinkButton
Vista style command link button
QDateEdit
Widget for editing dates based on the QDateTimeEdit widget
QDateTimeEdit
Widget for editing dates and times
QDial
Rounded range control (like a speedometer or potentiometer)
QDoubleSpinBox
Spin box widget that takes doubles
QFocusFrame
Focus frame which can be outside of a widget's normal paintable area
QFontComboBox
Combobox that lets the user select a font family
QLCDNumber
Displays a number with LCD-like digits
QLabel
Text or image display
QLineEdit
One-line text editor
QMenu
Menu widget for use in menu bars, context menus, and other popup menus
QProgressBar
Horizontal or vertical progress bar
QPushButton
Command button
QRadioButton
Radio button with a text label
QScrollArea
Scrolling view onto another widget
QScrollBar
Vertical or horizontal scroll bar
QSizeGrip
Resize handle for resizing top-level windows
QSlider
Vertical or horizontal slider
QSpinBox
Spin box widget
QTabBar
Tab bar, e.g. for use in tabbed dialogs
QTabWidget
Stack of tabbed widgets
QTimeEdit
Widget for editing times based on the QDateTimeEdit widget
QToolBox
Column of tabbed widget items
QToolButton
Quick-access button to commands or options, usually used inside a QToolBar
QWidget
The base class of all user interface objects
高级部件
QCalendarWidget
Monthly based calendar widget allowing the user to select a date
QColumnView
Model/view implementation of a column view
QDataWidgetMapper
Mapping between a section of a data model to widgets
QDesktopWidget
Access to screen information on multi-head systems
QListView
List or icon view onto a model
QMacCocoaViewContainer
Widget for Mac OS X that can be used to wrap arbitrary Cocoa views (i.e., NSView subclasses) and insert them into Qt hierarchies
QMacNativeWidget
Widget for Mac OS X that provides a way to put Qt widgets into Carbon or Cocoa hierarchies depending on how Qt was configured
QTableView
Default model/view implementation of a table view
QTreeView
Default model/view implementation of a tree view
QUndoView
Displays the contents of a QUndoStack
QWSEmbedWidget
Enables embedded top-level widgets in Qt for Embedded Linux
QWebView
Widget that is used to view and edit web documents
QX11EmbedContainer
XEmbed container widget
QX11EmbedWidget
XEmbed client widget
Phonon::VideoWidget
Widget that is used to display video
组织者部件
QButtonGroup
Container to organize groups of button widgets
QGroupBox
Group box frame with a title
QSplitter
Implements a splitter widget
QSplitterHandle
Handle functionality of the splitter
QStackedWidget
Stack of widgets where only one widget is visible at a time
QTabWidget
Stack of tabbed widgets
抽象部件类
QAbstractButton
The abstract base class of button widgets, providing functionality common to buttons
QAbstractScrollArea
Scrolling area with on-demand scroll bars
QAbstractSlider
Integer value within a range
QAbstractSpinBox
Spinbox and a line edit to display values
QDialog
The base class of dialog windows
QFrame
The base class of widgets that can have a frame
参考
Widgets and Layouts 4.8
摘自:http://www.cnblogs.com/rogerer/archive/2013/01/29/2881336.html
- 布局管理
- 布局管理
- 布局管理
- 使用布局管理器管理布局
- Java布局管理
- 布局管理LayoutManager
- PyQt4 - (4) 布局管理
- ALV 布局管理
- QT 布局管理
- Qt4 布局管理经验总结
- jscrollpane布局管理
- Android布局管理
- GTK+ 布局管理
- 【转】GTK+ 布局管理
- 布局管理简单认识
- Clutter 布局管理
- Android布局管理
- Qt布局管理
- cvSetData与imageData
- 页面之间的值传递
- 基于mean shift的图像分割
- 蓝牙、红外线与wifi 区别以及不同频段无线电磁波的穿墙和绕过障碍物能力
- 域名解析中A记录、CNAME、MX记录、NS记录的区别和联系
- 布局管理
- android eclipse ndk javah javap
- SetTimer 定时器的使用
- 比较两个有序集合
- C++学习 C++函数模板与类模板实例解析
- 在操作系统中,进程之间是如何通信的?
- 各种排序算法的稳定性
- Linux-(6)Vi/Vim的基本操作
- iphone 持久性存储