`
javasogo
  • 浏览: 1822003 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

QT(9)自定义layout[2] - Flow Layout

阅读更多

在上一次学习 QT(8)变动布局Dynamic Layout中,我们在此总结一下:对于修改布局,可以通过removeWidget后在根据新的位置重新加载。为了创建新的合适的布局,我们需要重新resize布局的大小。我们需要注意到在修订时,要考虑组建之间的空间,即spacing()。对如删和增都需要考虑QSize(spacing(),spacing())。

在本次,我们延续QT(7)的学习,再次对layout的继承进行学习。参考http://doc.qt.nokia.com/latest/layouts-flowlayout.html /。在此之前,我们对QT编译中碰到的一些问题进行记录:

问题1:编译中出现make : g++没有找到

对于ubuntu可以使用apt-get install g++,但是在采用yum的系统,例如MeeGo,没有g++的包,yum那里采用了另外的名字yum install gcc-c++。

问题2:编译中出现undefined reference to `vtable for xxxx(某个类名)'

出去这种情况,需要检查*.pro文件,看看是否将所需的*.h和*.cpp加入,或者加入一些空文件。

记录1:制定moc生成文件存放的目录

>moc命令将含Q_OBJECT的头文件转换成标准.h文件,在我们定义Q_OBJECT后,很可能会生成moc_xxxxx.cpp的文件。方式:MOC_DIR = build。

言归正卷,我们这次建立一个自定的layout,上面的widget,根据我们addWidget的先后顺序,从左向右排序,如果超过范围,就从下一排开始,也是从左向右,很像现代文字的书写方式。如图所示:

搭建程序框架

qtmain.cpp为主程序,mywindow.h和mywindow.cpp为窗口类,flowlayout.h和flowlayout.cpp是我们用于构造我们布局QLayout的子类。mywindow.cpp如下:

MyWindow :: MyWindow()
{
FlowLayout * layout = new FlowLayout();
layout->addWidget (new QPushButton(tr("Short")));
layout->addWidget (new QPushButton(tr("Longer")));
layout->addWidget (new QPushButton(tr("Different Text")));
layout->addWidget (new QPushButton(tr("More Text")));
layout->addWidget (new QPushButton(tr("This is a long text button!")));
setLayout(layout);
setWindowTitle("FlowLayout Test!");
}

构造自定义的布局QLayout子类:存放QLayoutItem

我们在QT(7)中学习过,这里我们使用一个QList<QLayoutItem *> itemList来存放我们的item,并且进行了addItem,count,itemAt(int index),takeAt(int index)这几个virtual方法,同时在释放方法~FlowLayout()中清空itemList,并释放空间。这里,将并在详细说明。可以参见参考中给出的源代码

完成构建函数

在MyWindow类中,我们并不需要有特别的构造函数。在Layout中,计算margin,也就是各widget之间的空隙是一个很麻烦的事情。在例子中,我们提供可定制margin(缺省值为11,由于缺省的边框为1,所以11大抵重视觉角度看就是10px),这是Layout之间的留边位置,同时我们也设定了组件之间的间隔大小(m_hSpace,m_vSpace),如下:

FlowLayout :: FlowLayout(QWidget * parent, int margin,int hSpacing,int vSpacing )
: QLayout(parent),m_hSpace(hSpacing),m_vSpace(vSpacing)
{
setContentsMargins(margin,margin,margin,margin);
}

这里我们看到一个有趣的写法,实际上其等同与在方法中运行了:

QLayout(parent);
m_hSpace = hSpacing;
m_vSpace = vSpacing;

给出Layout的尺寸大小

Qt::Orientations FlowLayout::expandingDirections() const
{
return 0;
}

这里我们要求button并会自动补充空白位置,所有给出0。对于Layout的尺寸大小,重要的是minimumSize()和sizeHint()两个。如下面。QSize可以通过要求增加某个尺寸大小的文字,它看自动进行调整计算,并需要我们精确计算。最佳大小,我们设置等同于最小尺寸。

QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem * item;
foreach(item,itemList)
size = size.expandedTo (item->minimumSize());
size += QSize(2*margin(),2*margin());
return size;
}

QSize FlowLayout::sizeHint() const
{
return minimumSize();
}

我们补充继承两个方法,用于获取组件之间间隔大小:

int FlowLayout::horizontalSpacing() const
{
if(m_hSpace >= 0)
return m_hSpace;
else
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing /* Default horizontal spacing for a QLayout.*/ );
}

int FlowLayout::verticalSpacing() const
{
if(m_vSpace >= 0 )
return m_vSpace;
else
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}

int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const //这是我们定义的private方法,用于从parent中获得widget之间的间隔
{
QObject * parent = this->parent();
if(!parent){
return -1;
}else if(parent->isWidgetType()){
QWidget * pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm,0,pw);
}else{
return static_cast<QLayout*>(parent)->spacing();
}
return 0;
}

进行布局

布局采用setGemetry,这个我们在QT(7)中也介绍过:

void FlowLayout::setGeometry(const QRect & rect)
{
QLayout::setGeometry(rect);
doLayout(rect,false);
}

下面我们根据需求,对doLayout进行说明:

int FlowLayout::doLayout(const QRect & rect, bool testOnly) const
{
int left,top,right,bottom;

getContentsMargins(&left,&top,&right,&bottom);
QRect effectiveRect = rect.adjusted (left,top,-right,-bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;

我们第一步,先计算有效的摆放widget的尺寸effectiveRect。

QLayoutItem * item;
foreach(item,itemList){
//It then sets the proper amount of spacing for each widget in the layout, based on the current style.
QWidget * wid = item->widget();
int spaceX = horizontalSpacing();
if(spaceX == -1)
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,QSizePolicy::PushButton,Qt::Horizontal);
int spaceY = verticalSpacing();
if(spaceY == -1)
spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton,QSizePolicy::PushButton,Qt::Vertical);

在这里,我们获取一些基本的数据,包括每一个item,其大小为item->sizeHint(),在水平方向各组件之间的间隔spaceX以及竖直方向的间隔spaceY。我们将在effectiveRect内顺序排列widget。下面我们来进行计算,设置各个item的setGeometry,需要获取每个item的起始左上角坐标。

int nextX = x + item->sizeHint().width() + spaceX; //下一个组件的左上角位置的x坐标
if(nextX - spaceX > effectiveRect.right() && lineHeight > 0){ //如果超出位置,换行 ,重新计算(x,y)坐标
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x+item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if(!testOnly) //设置item的位置
item->setGeometry (QRect(QPoint(x,y),item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight,item->sizeHint().height());
}

return y + lineHeight - rect.y() + bottom; //返回需要限制所有组件,layout至少要多高
}

对于setGeometry,我们并不需要返回值,但是我们发现,如果组件多,有多行摆放,有时无法全部显示,这在初始显示和我们改变window大小的时候可能会出现,而doLayout就返回了layout显示所有组件时至少需要的height。因此我在width改变是需要重新计算height,需要设置hasHeightForWidth()为true,并heightForWidth返回相应的值。

bool FlowLayout::hasHeightForWidth() const
{
return true;
}

int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0,0,width,0),true);
return height;
}

相关链接:我的MeeGo/Moblin相关文章

一个小故事:民国元年的小学国文教科书中有一篇《少年》:一少年在兵营为鼓手,某日,将校会宴,大将劝饮,少年辞曰:吾不嗜酒。大将曰:汝终日击鼓甚劳,可少饮 酒以舒之。少年固辞不饮,大将不悦。副将在旁,欲试之,厉声曰:汝必饮一杯,是军令也,违令将斩汝!少年改容曰:军令不胜恐惧,然饮酒非兵士职。昔者,吾父以酒疾不起,吾入营时,吾母戒曰:汝终身勿饮酒。虽有大将之命,。不能破慈母之戒。声泪俱下。坐中将校莫不感动。由是少年益受大将信任,有名于时。

这个故事告诉我们,什么叫做原则,原则不是领导说一句话,就可以摇摆和动摇。现在春节了,在酒桌上该不喝酒就不喝酒,劝酒是一个陋习。当然还有其他很多事情,做一个有良知的人。

分享到:
评论

相关推荐

    QtFlowlayout Qt流式布局器

    QtFlowlayout是一个专门为Qt开发的自定义布局器,它扩展了Qt的标准布局系统,使得在QWidget容器中可以灵活地自动布局子控件。这个库的主要目的是处理那些在大小和数量上变化不定的控件,例如在一个应用中,用户可能...

    Qt实现Windwos下文件预览样式---流式布局.rar

    在本文中,我们将深入探讨如何使用Qt库在Windows环境下实现文件预览的样式,特别是采用流式布局(Flow Layout)来模拟系统自带的文件图标预览功能。Qt是一个跨平台的C++图形用户界面应用程序开发框架,它提供了丰富...

    QML Book in Chinese

    #### 2. 初识Qt5 (Meet Qt5) - **序言 (Preface)** - 介绍了Qt5的历史背景和发展。 - **Qt5介绍 (Qt5 Introduction)** - Qt5概述:包括Qt5的核心特性、新功能以及与Qt4的区别。 - **Qt构建模块 (Qt Building ...

    商业编程-源码-对话框源代码 dlg_layout_mgr_demo.zip

    2. **流式布局**(Flow Layout):控件按行或列顺序排列,当空间不足时自动换行。 3. **相对布局**(Relative Layout):控件的位置相对于其他控件或对话框边缘来确定。 4. **锚点布局**(Anchor Layout):控件的...

    Qt Quick编程之Qt Quick元素布局,适合Qt初学者

    本文详细介绍了Qt Quick中的两种布局方式:定位器(Item Positioner)和布局管理器(Item Layout)。通过合理使用这些布局工具,开发者可以轻松地创建出既美观又响应式的用户界面。理解每种布局的特点及其应用场景对于Qt...

    如何使QtQML中ListView从底往上排列.docx

    layout: Flow { direction: Flow.BottomToTop cellWidth: listView.width cellHeight: delegate.height } reverseLayout: true } } ``` 在这个示例中,我们创建了一个包含两个对话条目的`ListView`。`Flow`...

    Qt/Embedded对话框设计

    Qt 一起提供的 customlayout样例展示了三个自定义布局管理器:BorderLayout、CardLayout 和 SimpleFlow,程序员可以使用并修改它们。 四、Qt 的对话框类 Qt 提供了多种对话框类,包括: 1. QMessageBox 类:是...

    flowlayout.zip

    Flow Layout。完成一个自定义布局类型FlowLayout,该类型的布局可分为水平布局和垂直 布局两种。水平布局在顶级部件中从左到右,从上到下排列子部件。当布局中的每一行空间不足时, 首先将这些项水平放置,然后垂直...

    QML元素详细介绍

    - **Connections/Component/Timer/QtObject/WorkerScript/Loader/Repeater/SystemPalette/FontLoader/LayoutItem**:提供各种实用工具和控件,如信号槽连接、组件封装、定时器、线程支持等。 #### 三、总结 通过...

    Learning_GUI.rar_learninggui_one more

    2. 布局管理:如何组织和排列这些控件,如网格布局(Grid Layout)、流式布局(Flow Layout)、盒式布局(Box Layout)和相对布局(Relative Layout)等,确保界面在不同分辨率和屏幕尺寸上看起来美观且功能正常。...

    QML语法详解

    ##### 2. 基本交互项 - **MouseArea**:用于捕捉鼠标的输入事件。 - **FocusScope**:管理键盘焦点的范围。 - **Flickable**:支持快速滑动查看内容。 - **Flipable**:允许内容翻转查看另一面。 ##### 3. 状态...

    widgetdemo

    4. **布局管理**:Widget在界面上的排列和定位需要通过布局管理器(Layout Manager)进行,如网格布局(Grid Layout)、流式布局(Flow Layout)、盒式布局(Box Layout)等,确保界面美观且适应不同屏幕尺寸。...

    用对话框,仿QQ菜单,稍修改可用

    这可以通过添加动态布局(Dynamic Layout)或流式布局(Flow Layout)实现。每个菜单项都是一个按钮或者控件,我们可以根据需要设置其文本、图标以及点击事件。 3. **菜单项的交互**:为实现点击一级菜单显示子菜单...

    Pyqt5 关于流式布局和滚动条的综合使用示例代码

    在PyQt5中,流式布局(Flow Layout)是一种灵活的布局管理器,它允许控件像流水一样自适应地填充窗口或容器。这种布局特别适用于需要动态添加或删除元素,且希望元素能够自然地扩展到下一行或下一列的情况。在本示例...

    An Introduction to C GUI Programming 2019.rar

    了解如何组织和定位GUI组件,例如网格布局(Grid Layout)、流式布局(Flow Layout)、边界布局(Border Layout)等,确保界面美观且适应不同屏幕尺寸。 7. **资源管理**: 图像、图标、字体等资源在GUI中扮演...

    python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)

    Python的GUI框架PyQt5为开发者提供了丰富的界面设计能力,其中一种高级的布局方式就是流式布局(Flow Layout),也称为瀑布流布局。这种布局方式常用于网页设计,但同样适用于桌面应用程序,尤其是在显示大量图片时...

    Mayavi 参考

    General layout of UI Visualizing data Modules Filters Interaction with the scene Mouse interaction Keyboard interaction From interactive usage to scripting The embedded Python interpreter ...

    layouts

    1. **流式布局(Flow Layout)**:元素按顺序从左到右排列,如果一行填满,则换行继续。这类似于文本的排列方式,如网页中的段落。 2. **网格布局(Grid Layout)**:将区域划分为行和列,元素在指定的单元格内定位...

    PythonGUI编程

    3. **布局管理**: 使用网格布局(Grid)、流式布局(Flow Layout)或盒式布局(Box Layout)等管理器,确保控件在窗口中的排列整齐有序。 4. **事件处理**: 绑定事件处理函数,当用户与控件交互时(如点击按钮、输入...

Global site tag (gtag.js) - Google Analytics