在上一次学习 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相关文章
一个小故事:民国元年的小学国文教科书中有一篇《少年》:一少年在兵营为鼓手,某日,将校会宴,大将劝饮,少年辞曰:吾不嗜酒。大将曰:汝终日击鼓甚劳,可少饮 酒以舒之。少年固辞不饮,大将不悦。副将在旁,欲试之,厉声曰:汝必饮一杯,是军令也,违令将斩汝!少年改容曰:军令不胜恐惧,然饮酒非兵士职。昔者,吾父以酒疾不起,吾入营时,吾母戒曰:汝终身勿饮酒。虽有大将之命,。不能破慈母之戒。声泪俱下。坐中将校莫不感动。由是少年益受大将信任,有名于时。
这个故事告诉我们,什么叫做原则,原则不是领导说一句话,就可以摇摆和动摇。现在春节了,在酒桌上该不喝酒就不喝酒,劝酒是一个陋习。当然还有其他很多事情,做一个有良知的人。
分享到:
相关推荐
源码使用Qt4.8.6和Qt5.7.1编译均没有问题。源码解释请参考博客:https://blog.csdn.net/baidu_33850454/article/details/81773323
Qt qt-opensource-windows-x86-5.11.0安装包,适用于开发openCV、QtAndroid
C++ Qt进阶之复杂控件自定义 --源代码,C++ Qt进阶之复杂控件自定义 --源代码C++ Qt进阶之复杂控件自定义 --源代码C++ Qt进阶之复杂控件自定义 --源代码
1、qt-everywhere-src-5.12.12的源代码 2、编者编译Qt5.12.12所使用的代码一并上传,方便大家下载编译.
qt-vs-addin-1.2.5.part3
qt-vs-tools-msvc2013-2.1.1 安装以后就可以在Visual Studio中找到QT VS TOOLS了。 软件的具体功能问百度吧。
qt-vs-addin-1.1.11-opensource.part2
从Qt官网上下载的Qt的解决方案资料库(Qt Solutions Archive) ... 有JPEG2000的,有Windows中Services的,有浏览器插件的,...http://qt.gitorious.org/qt-solutions/qt-solutions/trees/master/qtjp2imageformat 下载。
qt-vs-tools-msvc2015-2.1.1(直接安装即可将qt作为插件安装到VS2015软件上)亲测成功
qt-creator-linux-x86-opensource-1.3.0
vs2017的qt插件qt-vsaddin-msvc2017-2.8.1-rev.06.vsix.rar
qt-creator-linux-x86_64-opensource-2.6.1.bin
qtcharts-opensource-src-5.7.0
qt-vs-addin-1.2.4-opensourceQt,坦白来说,并不只是一个界面库,他是C++编程思想的集大成者。它是得到完善的C++应用程序框架。使用Qt,在一定程度上你获得的是一个“一站式”、“全方位”的解决方案,STL。string...
qt-opensource-windows-x86-msvc2015_64-5.8.0:vs2015版本的qt,解决官网下载不了的问题,已存在百度网盘
Qt编写自定义控件15-百分比仪表盘-附件资源
qt-creator-2.8.0 for Linux源文件
qt5.12.9源码,嫌官网下载太慢可以在这里下载。移植qt到arm设备需用到此源码
qt-vs-addin-1.2.5.part2
qt-creator-win-opensource-2.3.1.exe qt-creator-win-opensource-2.3.1.exe qt-creator-win-opensource-2.3.1.exe