QML学习笔记(五)QML新手入门其三:通过Row和Colunm进行简单布局
前言
在上一节中,我们已经对Rectangle有比较深入的了解,在接下来的内容中,我们将首次了解有关布局的方法,并创建多个Rectangle,尝试对它们进行简单的布局。
一、Row和Column的使用
我们知道,在QWidget中实现自伸缩的布局,基本上围绕不开水平布局QHBoxLayout和垂直布局QVBoxLayout这两个布局类,当然它们并不是具体的控件,而是一个透明隐形的布局规则,需要将他设置在某个窗口之中,例如QWidget->setLayout();。
在Qml中,有Row和Colunm两个组件能和这两个布局对应。
我们先创建出两个新的Rectangle,一共三个,并为它们设置不同的id名字和不同的背景颜色。
再然后,我们直接用一个Row{}来将它们全部包含起来,完整代码如下:
import QtQuick 2.14
import QtQuick.Window 2.14Window {visible: truewidth: 640height: 480title: qsTr("QML Syntax Demo")Row{Rectangle{id: redRectIdwidth: 100height: 100color: "red"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("One")}}}Rectangle{id: blueRectIdwidth: 100height: 100color: "blue"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("Two")}}}Rectangle{id: greenRectIdwidth: 100height: 100color: "green"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("Three")}}}}
}
运行看下效果:
我们可以看到,代码中其实并没有对这三个矩形有任何坐标上的设置,Row这个东西直接根据他们的尺寸,做了横向的布局,并默认显示在左上角。
我们将Row换成Colunm,代码我就不放上来了,直接看结果。
Colunm和Row效果是类似的。
那么它们是否可以设置坐标呢?我们可以添加xy值,看看效果。
看上去完全可以哦。
那能不能用anchors.centerIn: parent这种方式呢?试下看看:
看来是可以的!上下左右水平居中,并且改变边缘尺寸,还是居中的。
我们再将Row和Colunm做一些组合,比方说上面是红矩形,下面是蓝绿矩形。代码如下:
Column{anchors.centerIn: parentRow{Rectangle{id: redRectIdwidth: 100height: 100color: "red"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("One")}}}}Row{Rectangle{id: blueRectIdwidth: 100height: 100color: "blue"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("Two")}}}Rectangle{id: greenRectIdwidth: 100height: 100color: "green"border.color: "black"border.width: 5radius: 20MouseArea{anchors.fill: parentonClicked: {console.log("Three")}}}}}
运行看下效果
唔,确实如我所说,但我本来以为红色会在蓝色绿色的中间,也就是金字塔一样的,结果看来并不是呢。这里我们要理解一个点,就是按照这样默认的方式布局,第一个Row实际上占据的位置是Col这个正方形的上半部分区域,如图:
而红色矩形在里面虽然是水平布局,但因为左右都没有其他组件,也没有弹簧这些东西,所以默认还是左上角的。
虽然这一点很好理解,但有趣的是,这和QHBoxLayout是不一样的。在QHBoxLayout中只添加一个按钮控件,默认是居中的。我可以在布局管理器中简单看看效果:
二、试图解决红色矩形不居中的问题
回到qml的布局里面,我们可能想当然地会对红色矩形设置一下anchors.centerIn: parent,可结果并不如我们的预期:
属于是相当奇怪了!!
那到底需要怎么做呢?我稍微钻研地学习了一下,发现还真没这么简单。Row和Colunm作为简单的布局容器,默认会根据子项的尺寸来改变尺寸,并没有提供弹簧这种直接操作的功能(可能有误,欢迎指正)。
我实在不信邪,于是给第一个row强行设置了固定尺寸,并设置红色矩形是水平居中的,这时是符合预期的。
但这种做法太不灵活了,实际开发中不可能会对Row固定尺寸的。(我们对于设置固定数值的地方一定要非常敏感,后期是需要把这些东西规整出来写成参数,甚至还要写在配置文件里。)
如果取消设置Row的尺寸,你会发现一切乱套了,我甚至不能理解背后的具体逻辑。
后面百度了一下,发现原来还有其他更深层次的布局组件,如RowLayout和ColumnLayout这些,它们也许有更多可供设置的功能。
或者我们换一种思路吧,直接添加空白的矩形去填充它,模拟弹簧然后设置抢占空间的策略,比如expanding什么的,但我不确定有没有这种属性。
虽然有些气馁,但目前来说我还只是初学者,可能真的没办法搞懂这些东西。
我再总结一下吧,Row默认情况下会跟随内部子项的大小来调整大小,但在上文这种特殊情况下会被拉长,导致子项在内部无法居中。这个时候要通过一些特殊的策略来进行布局,或者改用更高级的布局容器,但现阶段我们只关注语法即可!
三、Row和Colunm的其他属性
我们回档一下代码,变回这种布局。
我们可以通过增加spacing,来调整布局和组件之间的间距。
我们还可以通过设置padding设置布局中的默认边距。
这里效果就很明显了,红色矩形明显往右进行了偏移,距离是20像素点。
但这里又有一个问题,padding的设置默认是上下左右一样的,如果我想要单独设置左边距的话,是不行的。
经查找资料得知,在RowLayout中是可以实现的,设置Layout.leftMargin: 20即可。
最后附上一个链接,可以去看一下。
QML 中 的 Row 和 RowLayout对比
四、总结
看来真正学会布局的任务还是道阻且长啊。但是没关系,后面会重点专门去学习布局相关的内容,然后实现任一我想要实现的布局方式。
其实也没差多少了,就是弹簧和居中布局的问题嘛。
加油吧!