QML中RowLayout和row区别,实现类似于前端那样的布局方式

一. 内容简介

QML中RowLayout和row区别,想实现类似于前端那样的布局方式

二. 软件环境

2.1 QT 5.14.1

编译器用的,
QT编译器采用的是MSVC2017 64bit
在这里插入图片描述

三. 主要流程

3.1 Row

QT官方文档中Row继承于item,也就是说item有的,row也都有的
item的属性,

activeFocus : bool
activeFocusOnTab : bool
anchors
anchors.alignWhenCentered : bool
anchors.baseline : AnchorLine
anchors.baselineOffset : real
anchors.bottom : AnchorLine
anchors.bottomMargin : real
anchors.centerIn : Item
anchors.fill : Item
anchors.horizontalCenter : AnchorLine
anchors.horizontalCenterOffset : real
anchors.left : AnchorLine
anchors.leftMargin : real
anchors.margins : real
anchors.right : AnchorLine
anchors.rightMargin : real
anchors.top : AnchorLine
anchors.topMargin : real
anchors.verticalCenter : AnchorLine
anchors.verticalCenterOffset : real
antialiasing : bool
baselineOffset : int
children : list<Item>
childrenRect
childrenRect.height : real
childrenRect.width : real
childrenRect.x : real
childrenRect.y : real
clip : bool
containmentMask : QObject*
data : list<QtObject>
enabled : bool
focus : bool
height : real
implicitHeight : real
implicitWidth : real
layer.effect : Component
layer.enabled : bool
layer.format : enumeration
layer.live : bool
layer.mipmap : bool
layer.samplerName : string
layer.samples : enumeration
layer.smooth : bool
layer.sourceRect : rect
layer.textureMirroring : enumeration
layer.textureSize : size
layer.wrapMode : enumeration
opacity : real
palette : Palette
parent : Item
resources : list<QtObject>
rotation : real
scale : real
smooth : bool
state : string
states : list<State>
transform : list<Transform>
transformOrigin : enumeration
transitions : list<Transition>
visible : bool
visibleChildren : list<Item>
width : real
x : real
y : real
z : real

和前端的比较:

  1. Row排列方式和前端是一样的(横竖堆叠),Row设置的x是没办法生效的,然后元素就按着写的顺序排列的
  2. 前端元素间添加margin很方便,Row或者是说没有布局时候,添加margin都要先指定锚点,然后再设置margin,而且其他元素想要和该元素对齐时候,margin基本都被忽略了,还要自己手动算一下的,手动加上去
  3. 如果1,2间距10,.2,3间距20的话,Row是没有办法满足需求的,Row又只能设置所有的间隔,单个间隔又要设置锚点,
    在这里插入图片描述
add : Transition
bottomPadding : real
effectiveLayoutDirection : enumeration
layoutDirection : enumeration
leftPadding : real
move : Transition
padding : real
populate : Transition
rightPadding : real
spacing : real
topPadding : real

3.2 RowLayout

RowLayout也是继承item,下面是他自己的属性,

// 设置元素尺寸
Layout.minimumWidth // 最小尺寸
Layout.minimumHeight // 最小尺寸
Layout.preferredWidth // 最小尺寸
Layout.preferredHeight // 最小尺寸
Layout.maximumWidth // 最小尺寸
Layout.maximumHeight // 最小尺寸
// 设置元素尺寸
Layout.fillWidth // 去除其他元素后,充满剩余尺寸
Layout.fillHeight // 去除其他元素后,充满剩余尺寸
// 设置对齐方式(对齐文本)
Layout.alignment 
Qt::AlignLeft
Qt::AlignHCenter
Qt::AlignRight
Qt::AlignTop
Qt::AlignVCenter
Qt::AlignBottom
Qt::AlignBaseline
// 设置margin
Layout.margins
Layout.leftMargin
Layout.rightMargin
Layout.topMargin
Layout.bottomMargin
// 设置拉伸因子
Layout.horizontalStretchFactor
Layout.verticalStretchFactor
// https://blog.csdn.net/qq_45179361/article/details/130480514(这个里面讲了拉伸因子)

和前端比较,要吐槽的点太多了

  1. RowLayout管的事情太多了,x,y没有办法设置了,而且部分控件的大小都会由layout管理了(button),而且间距,横向纵向都被layout管理(自己不能设置),使用起来不方便,感觉和前端的逻辑很不相符,刚开始使用时不知道这些,就会返现layout难用的要死,好多东西都改不了,总结就是位置控件大小以及控件间隔(横向纵向)都不能由自己管理
  2. 开始解决上面的问题,第一个问题控件位置,感觉QMl中之前的,x,y直接设置位置其实并不是很好,row那样就很类似前端的逻辑了,只是magin及其不方便,而RowLayout里面是这样的,会发现右边那个控件的位置的精确位置不知道,就很难受,如果向row那样就好了,
    在这里插入图片描述
    然后就可以用上Layout.preferredWidth这个属性了,在最下面加一个包含这个属性的控件,这个逻辑就很像前端里面的逻辑了,间隔时因为spacing由默认值,改成0就可以了,然后这个时候Layout.Margins用来设置空间的margin,因为QML中布局什么查看不如前端方便,我都会在家一个clip: true,就是会给超出父控件大小的子控件进行裁剪,就是有些大小没写,就可以直接看出来了,
    在这里插入图片描述
    还可以这样放.
    在这里插入图片描述
  3. 控件大小用width,height设置是没有效果的,部分控件由layout管理的,就直接用Layout.preferredWidth这些设置就可以了
  4. 控件间隔,一种是Layout.margins设置,和前端逻辑一样,另外一种用锚点先到给对齐,然后设置间隔,直接设置间隔是没有效果的
  5. 也就是说些控件大小,间隔什么的都要layout里面的那些东西写,原来的都不能用了,养成习惯就好了,而且在用了layout布局以后,锚点那些东西就会用的很少很少了,基本用不上,都按着前端那套逻辑走就可以了
    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 0
        clip: true
        Rectangle {
            color: 'teal'

            Layout.preferredWidth: 110
            Layout.preferredHeight: 110
            Layout.rightMargin: 20

            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            color: 'plum'
            Layout.preferredWidth: 100
            Layout.preferredHeight: 100
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 0
        clip: true
        Rectangle {
            color: 'teal'

            Layout.preferredWidth: 110
            Layout.preferredHeight: 110
            Layout.rightMargin: 20

            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            color: 'plum'
            Layout.preferredWidth: 100
            Layout.preferredHeight: 100
            Layout.alignment:AlignRight
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            height:100
            color: 'red'
            Layout.fillWidth: true
        }


    	}
    }

  1. fillWidth使用,现在这种情况呢,就是被按钮分成了三块区域,这三块区域等分,

在这里插入图片描述

Rectangle{
    Layout.preferredWidth: parent.width*1/10
    Layout.fillWidth: true                    
}
Button{
    layout.preferredWidth: 50
}

Rectangle{
    Layout.preferredWidth: parent.width*1/10
    Layout.fillWidth: true                    
}
Button{
    layout.preferredWidth: 50
}
Rectangle{
    Layout.preferredWidth: parent.width*1/10
    Layout.fillWidth: true                    
}

然后中间那个改成2/10,就可以通过这个来设置这些占位的大小了
在这里插入图片描述

补充:
ColumnLayout在布局时候,对元素竖向排列都是和前端一样的,但是在水平方向上,他会直接让Rectangle居中,上边的例子也可以看出

但是当里面是这样的时候,image,text,时候他们还是会竖向排列,但是水平方向上就不是水平排列的了,就是靠着左边排列的

//            contentItem: ColumnLayout{
//                width: parent.width
//                height: parent.height
//                Layout.alignment: Qt.AlignHCenter

//                Image{
//                    Layout.preferredHeight: 60
//                    source: "qrc:/images/music"
//                    Layout.fillWidth:true
//                    fillMode: Image.PreserveAspectFit

//                }

//                Text {
//                    text: qsTr("续加仪")
//                    Layout.fillWidth: true
//                    horizontalAlignment: Text.AlignHCenter
//                    font.pixelSize: 18
//                    color: "#8573a7ab"
//                    font.family: window.mFONT_FAMILY
//                    font.bold: true
//                }
//                Text {
//                    text: qsTr("这是我的Cloud Music Player")
//                    Layout.fillWidth: true
//                    horizontalAlignment: Text.AlignHCenter
//                    font.pixelSize: 16
//                    color: "#8573a7ab"
//                    font.family:  window.mFONT_FAMILY
//                    font.bold: true
//                }
//                Text {
//                    text: qsTr("www.hyz.cool")
//                    Layout.fillWidth: true
//                    horizontalAlignment: Text.AlignHCenter
//                    font.pixelSize: 16
//                    color: "#8573a7ab"
//                    font.family:  window.mFONT_FAMILY
//                    font.bold: true
//                }
//            }

在这里插入图片描述

用Rectangle包裹一下是这样

        contentItem: ColumnLayout{
            anchors.fill: parent
            clip: true
            spacing: 0
            Layout.alignment: Qt.AlignHCenter

            // Layout在放置时候都是自动居中的,所以宽度合适,他就自己居中了
            Rectangle{
                Layout.alignment: Qt.AlignHCenter
                clip: true
                
                Layout.preferredHeight: 60
                Layout.preferredWidth: 60
                color: "red"
                Image{
                    // 可以让里面文字或者内容居中对齐
                    width: 60
                    height: 60
                    source: "qrc:/images/music"
                    // 宽度自适应
                }

            }



            Rectangle{
                color: "red"
                clip: true
                Layout.preferredHeight: 40
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignHCenter
                Text {
                    width: parent.width
                    height: parent.height
                    text: qsTr("Cloud Music")

                    font.pixelSize: 16
                    color: "#8573a7ab"
                    font.family:  window.mFONT_FAMILY
                    font.bold: true
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
            }

            Rectangle{
                Layout.fillHeight: true


            }


        }

在这里插入图片描述
感觉布局还是先用Rectangle划分好就行了,就和前端一样用div划分的,
直接在布局中还是不要用text,image这些控件,感觉不是特别可控,写好的样式,可能改一些其他东西,他的布局就路乱了(看视频里面调了好久,然后还不太理解,Rectangle更好理解一些),Rectangle设置背景色比较容易,还是比较容易调整布局的,还是尽量都用Rectangle,在Layout下面

四. 参考

Item QML Type https://doc.qt.io/qt-6/qml-qtquick-item.html
Row QML Type https://doc.qt.io/qt-6/qml-qtquick-row.html
RowLayout QML Type https://doc.qt.io/qt-6/qml-qtquick-layouts-rowlayout.html

<think>好的,用户现在问的是QMLRowRowLayout区别。之前他们已经询问过QML的布局组件,我给出了一个比较全面的介绍,里面提到了RowRowLayout都属于水平布局,但需要更详细地区分两者。 首先,我需要确认用户的使用场景。可能他们在实际开发中遇到了布局问题,比如元素尺寸管理或者动态调整的问题,导致他们需要更深入理解这两个组件的区别。用户可能已经尝试过Row,但发现某些情况下布局不够灵活,尤其是在需要子元素自动拉伸或者约束尺寸的时候,这时候RowLayout可能更适合。 接下来,用户的需求是什么?他们需要明确的区别,包括功能、使用场景以及如何选择。可能他们在设计一个需要响应式布局的界面,或者在处理不同屏幕尺寸时需要更精细的控制。这时候,RowLayout的高级特性,比如尺寸约束填充,就变得重要了。 然后,我需要考虑用户可能的深层需求。他们可能对布局机制不太熟悉,或者在使用过程中遇到了子元素重叠、布局错位的问题。这时候,解释两者的内部机制,比如Row是基于位置排列而RowLayout使用布局管理器,会帮助他们理解为何在某些情况下RowLayout更合适。 在之前的回答中,我提到RowLayout属于高级布局模块,需要导入QtQuick.Layouts,并且支持尺寸约束动态拉伸。现在需要更详细地展开这些点,对比Row的局限性。例如,Row只能设置间距方向,而子元素的大小需要手动设置,而RowLayout允许子元素通过Layout属性定义自己的行为,比如填充剩余空间或者设置最小最大尺寸。 另外,要注意示例的使用,通过代码示例展示两者在相同场景下的不同表现,这样用户能更直观地理解差异。例如,在Row中,子元素可能不会自动调整宽度,导致超出父容器或者留白,而RowLayout可以通过Layout.fillWidth: true让子元素填满空间。 还要提到性能方面,Row更简单,适合轻量级布局,而RowLayout功能更强大但可能有更高的开销。这对于需要优化性能的应用来说是一个考虑点。 总结来说,回答需要结构清晰,分点列出区别,包括功能特性、使用方式、子元素控制、布局行为适用场景,每个部分用例子对比说明。确保用户能够根据他们的具体需求选择合适的组件。</think>在 QML 中,`Row` `RowLayout` 虽然都能实现水平排列子元素,但它们的核心机制使用场景有显著差异。以下是结构化对比: --- ### **一、基础特性对比** | 特性 | `Row` | `RowLayout` (需导入 `QtQuick.Layouts`) | |--------------------|--------------------------------|---------------------------------------| | **定位方式** | 简单顺序排列 | 基于布局管理器动态计算 | | **尺寸控制** | 仅支持固定尺寸 | 支持动态尺寸约束(最小/最大/填充) | | **依赖项** | 原生组件无需导入 | 需导入 `QtQuick.Layouts 1.15` | | **性能** | 轻量级 | 稍重(因布局计算) | --- ### **二、核心差异详解** #### 1. **子元素控制方式** - **`Row`**: - 子元素直接设置 `width/height` ```qml Row { spacing: 5 Rectangle { width: 50; height: 50; color: "red" } // 固定尺寸 Rectangle { width: 100; height: 50; color: "blue" } } ``` - **`RowLayout`**: - 子元素通过 `Layout.*` 附加属性控制行为 ```qml RowLayout { spacing: 5 TextField { Layout.fillWidth: true } // 填充剩余宽度 Button { Layout.preferredWidth: 100 } // 设置推荐宽度 } ``` #### 2. **动态尺寸调整** - **`Row`**: - 子元素不会自动拉伸或收缩 - 总宽度 = 所有子元素宽度 + 间距总 - **`RowLayout`**: - 自动分配剩余空间(通过 `Layout.fillWidth: true`) - 支持约束: ```qml Layout.minimumWidth: 50 Layout.preferredWidth: 100 Layout.maximumWidth: 200 ``` #### 3. **嵌套兼容性** - **`Row`**: - 可自由嵌套其他容器(如 `Column`、`Grid`) - **`RowLayout`**: - 需与同模块布局(`ColumnLayout`/`GridLayout`)配合使用 - 禁止直接嵌套非布局组件(否则破坏布局计算) --- ### **三、典型场景对比** #### 场景 1:固定尺寸元素排列 ```qml // 使用 Row 更简单高效 Row { spacing: 10 Button { width: 80; text: "取消" } Button { width: 80; text: "确认" } } ``` #### 场景 2:自适应宽度输入框+按钮 ```qml // 必须使用 RowLayout 实现动态填充 RowLayout { spacing: 5 TextField { Layout.fillWidth: true } // 输入框自动拉伸 Button { text: "提交" } // 按钮保持默认尺寸 } ``` --- ### **四、选择指南** | **使用 `Row` 当** | **使用 `RowLayout` 当** | |--------------------------------------|--------------------------------------| | 子元素尺寸固定且无需动态调整 | 需要子元素自适应容器尺寸 | | 布局层级简单(避免性能损耗) | 需要精确控制尺寸约束(最小/最大宽度)| | 快速实现基础水平排列 | 与其他高级布局(如 GridLayout)配合 | --- ### **五、陷阱规避** 1. **`RowLayout` 常见错误**: ```qml RowLayout { // ❌ 错误:直接设置子元素 width 会覆盖布局属性 TextField { width: 200 } // ✅ 正确:通过 Layout.* 控制 TextField { Layout.preferredWidth: 200 } } ``` 2. **混用问题**: ```qml ColumnLayout { Row { // ❌ 破坏布局计算 // ... } } ``` --- ### **六、性能优化建议** - 优先用 `Row` 实现简单布局 - 仅在需要动态调整尺寸时使用 `RowLayout` - 避免深层嵌套布局(超过 3 层时考虑重构) 通过理解这些差异,可以更精准地选择适合当前场景的布局组件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值