QML学习笔记(五)QML新手入门其三:使用Row和Colunm进行简单布局

前言

在上一节中,我们已经对Rectangle有比较深入的了解,在接下来的内容中,我们将首次了解有关布局的方法,并创建多个Rectangle,尝试对它们进行简单的布局。

一、Row和Column的使用

我们知道,在QWidget中实现自伸缩的布局,基本上围绕不开水平布局QHBoxLayout和垂直布局QVBoxLayout这两个布局类,当然它们并不是具体的控件,而是一个透明隐形的布局规则,需要将他设置在某个窗口之中,例如QWidget->setLayout();。

在Qml中,有Row和Colunm两个组件能和这两个布局对应。

我们先创建出两个新的Rectangle,一共三个,并为它们设置不同的id名字和不同的背景颜色。

再然后,我们直接用一个Row{}来将它们全部包含起来,完整代码如下:

cpp 复制代码
import QtQuick 2.14
import QtQuick.Window 2.14

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("QML Syntax Demo")

    Row{
        Rectangle{
            id: redRectId
            width: 100
            height: 100
            color: "red"
            border.color: "black"
            border.width: 5
            radius: 20
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("One")
                }
            }
        }

        Rectangle{
            id: blueRectId
            width: 100
            height: 100
            color: "blue"
            border.color: "black"
            border.width: 5
            radius: 20
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("Two")
                }
            }
        }

        Rectangle{
            id: greenRectId
            width: 100
            height: 100
            color: "green"
            border.color: "black"
            border.width: 5
            radius: 20
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("Three")
                }
            }
        }
    }
}

运行看下效果:

我们可以看到,代码中其实并没有对这三个矩形有任何坐标上的设置,Row这个东西直接根据他们的尺寸,做了横向的布局,并默认显示在左上角。

我们将Row换成Colunm,代码我就不放上来了,直接看结果。

Colunm和Row效果是类似的。

那么它们是否可以设置坐标呢?我们可以添加xy值,看看效果。

看上去完全可以哦。

那能不能用anchors.centerIn: parent这种方式呢?试下看看:

看来是可以的!上下左右水平居中,并且改变边缘尺寸,还是居中的。

我们再将Row和Colunm做一些组合,比方说上面是红矩形,下面是蓝绿矩形。代码如下:

cpp 复制代码
Column{
        anchors.centerIn: parent
        Row{
            Rectangle{
                id: redRectId
                width: 100
                height: 100
                color: "red"
                border.color: "black"
                border.width: 5
                radius: 20
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        console.log("One")
                    }
                }
            }
        }
        Row{
            Rectangle{
                id: blueRectId
                width: 100
                height: 100
                color: "blue"
                border.color: "black"
                border.width: 5
                radius: 20
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        console.log("Two")
                    }
                }
            }

            Rectangle{
                id: greenRectId
                width: 100
                height: 100
                color: "green"
                border.color: "black"
                border.width: 5
                radius: 20
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        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对比

四、总结

看来真正学会布局的任务还是道阻且长啊。但是没关系,后面会重点专门去学习布局相关的内容,然后实现任一我想要实现的布局方式。

其实也没差多少了,就是弹簧和居中布局的问题嘛。

加油吧!

相关推荐
Nicholas682 小时前
flutter视频播放器video_player_avfoundation之FVPVideoPlayerPlugin(一)
前端
姝孟2 小时前
笔记(C++篇)—— Day 10
笔记·学习
Ting_橘子2 小时前
Ajax&Json
前端·ajax·json
2501_916013742 小时前
Web 抓包全指南 Web抓包工具、浏览器抓包方法、HTTPS 解密
前端·网络协议·ios·小程序·https·uni-app·iphone
海涛高软3 小时前
QT 两种库写法 LIBS += .a和LIBS += -L -l
前端·javascript·qt
好学且牛逼的马3 小时前
GO实战项目:流量统计系统完整实现(Go+XORM+MySQL + 前端)
前端·mysql·golang
Beginner x_u3 小时前
Vue 3 项目实战教程大事件管理系统 (一):从零开始搭建项目基础
前端·javascript·vue.js·pinia
aesthetician3 小时前
ahooks:一套高质量、可靠的 React Hooks 库
前端·react.js·前端框架
shizhenshide3 小时前
如何在同一站点支持多版本的 reCAPTCHA 的兼容性方案
服务器·前端·网络·安全·captcha·ezcaptcha