当前位置: 首页 > article >正文

QT- QML Layout+anchors 布局+锚点实现窗口部件权重比例分配

布局管理

  • 简单比较两种界面管理
  • 锚点布局实现比例布局
  • 布局管理实现比例布局
    • 循环依赖问题简谈

在日常打螺丝中,我们偶尔会需要实现界面各组件能按比例放置,自适应各种分辨率的需求。我用锚点和布局都实现过相关界面,记录下来两种方式实现的差异。跟大家一起学习。

简单比较两种界面管理

特性布局系统锚点系统
排列方式自动流式布局精确相对定位
比例控制内置权重分配机制需手动计算百分比
嵌套复杂度适合多层嵌套结构适合扁平化结构
动态调整自动响应容器尺寸变化需绑定尺寸信号
典型应用表单布局/工具栏/等间距排列悬浮元素/固定边栏/叠加层

锚点、排列的简单介绍

这两者并不是严格分开使用,经常会混用,比如有时候用锚点分区域,然后用Layout布局控制里面的细节,或者用Layout 控制布局,里面用anchors控制小细节。


锚点布局实现比例布局

QML锚点系统(anchors)提供基于相对关系的布局方式,通过元素间的空间关系实现精准定位。比较直观,使用起来很方便。
常用接口:

  • anchors.left: parent.right ,本组件的左边是父组件的左边,相对定位设置 ,还有right 、top 、bottom等
  • anchors.centerIn: parent ,在父组件里正中央 居中
  • anchors.margins:30, 整体边距控制 或单独设置topMarginbottomMarginleftMarginrightMargin
  • anchors.horizontalCenter: parent.horizontalCenter, 相对父组件水平居中
  • anchors.verticalCenter parent.verticalCenter, 相对父组件垂直居中

实现没有什么约束(或者是我目前的场景没有遇到), 直接根据相对比例,计算即可。一般这样的话,根组件(或者依赖的父组件)要确定好大小,或者成为子组件。

property int ratio : 0.2 // 可以独立成属性,方便修改管理Item {id: containerwidth: 400; height: 300Rectangle {  // 标题(20%)id: headercolor: "lightgreen"anchors {top: parent.topleft: parent.leftright: parent.right}height: container.height * ratio }Rectangle {  // 内容(80%)color: "lavender"anchors {top: header.bottombottom: parent.bottomleft: parent.leftright: parent.right}height: container.height * (1-ratio )}
}

布局管理实现比例布局

所有用布局管理器(如 RowLayout、ColumnLayout)管理的组件都会自动拥有Layout.xxxx 相关的属性,可以设置它们来控制布局实现。我个人比较推荐使用这种方式,当然有不同想法也欢迎评论区讨论
常用接口:

  • Layout.alignment: Qt.AlignTop, 控制对齐方式, 有水平居中Qt.AlignHCenter 左对齐Qt.AlignLeft 等
  • Layout.fillWidth: true, 控制是否填满宽度,高度是fillHeight
  • Layout.margins: 16 ,整体边距控制 或单独设置leftMargin / topMargin
  • Layout.preferredWidth: 50, 设定首选宽度是50, minimumHeight是最小

QT 在Qt 6.2+里提供了一个更直观的比例分配属性 Layout.weight。它不需要手动设置fillXXX,直接在兄弟组件之间设定即可。
但目前(2025年)Qt 5.6.3+ 商用还是会收费,所以本文推荐的做法在 Qt 5.x 和 QtQuick.Layouts 1.x 中是可用的。

用Layout布局管理实现比例分配有三个要点:

  • 按比例分配:同时设置 Layout.fillxxx: true 和 Layout.preferredxxx,这样布局里的组件就会以preferredxxx作为比例因子,在分辨率变时组件相对大小保持不变。
  • 固定像素:仅设置 Layout.preferredxxxx(不设置 fillxxxx)就会变成按给定的值固定属性
  • 避免循环依赖:不要直接绑定 parent.width 或 parent.height,而是通过布局系统的内置机制实现自适应。

什么意思? 给举两个例子就明白了:

一,正确按比例分配(低于Qt 6.2) : 
两个chilstool会按照 82 的比例分配,且在窗口分辨率变化的情况下,比例依然不变:
如果想进一步细致控制,加大就行: 78 : 22,只需保证所有子项加起来 =1=10 或者 =100能整除的就行ColumnLayout
{anchors.fill: parentRectangle{  // 标题(20%)color: "white"Layout.fillWidth: trueLayout.fillHeight: trueLayout.preferredHeight: 2  //0.2也行 比例系数 2 / (2+8) /******/}Rectangle{  // 内容(80%)color: "white"Layout.fillWidth: trueLayout.fillHeight: trueLayout.preferredHeight: 8  //0.8也行 比例系数 8 / (2+8)/******/}
}

二,布局的循环分配 : 
父引用子,子引用父,导致计算出错:
这个其实算是我踩的坑,还以为和锚点一样的用法,被fillxxxx字面意义带偏了。记录一下ColumnLayout {anchors.fill: parentRowLayout {id: childlayoutLayout.fillHeight: true Layout.fillWidth: true  // 会先考虑子控件的宽Rectangle {id: chilstoolLayout.fillHeight: trueLayout.preferredWidth: parent.width * 0.8 // 又依赖父控件的宽color: "#ffffff"}Rectangle {id: chilstool2Layout.fillHeight: trueLayout.preferredWidth: parent.width * 0.2color: "#ffffff"}}}


循环依赖问题简谈

QML 的布局系统在计算尺寸时遵循以下步骤:

父布局管理器 子布局组件 子项目 这段fillXXX 不参与,隐式计算为共有 1. 收集尺寸提示 查询 implicitWidth/Height 返回隐式尺寸 报告自身尺寸需求 2. 计算布局分配 按优先级处理: Minimum > Preferred > Maximum fillXXX 就发生在这个阶段 3. 分配最终尺寸 4. 设置子项目几何 5. 子项目内部布局 6. 布局完成信号 父布局管理器 子布局组件 子项目

fillWidth/fillHeight 并不发生在隐式尺寸计算阶段。它类似给父控件声明“我不知道我尺寸如何,但我要占用你剩下的空间” 。 所以在隐式尺寸计算阶段,它的尺寸是未确定的,而在隐式尺寸计算阶段,又需要获知子控件的尺寸,若此时子控件又依赖父控件的尺寸,QML尺寸计算就会陷入循环依赖,引发了错误。
从分析上能获知,想破坏循环依赖,其实就是确定好子控件或父控件的尺寸,或者正确设定比例权重分配,打破循环。

  • 所以日常打螺丝中,注意布局管理器下的fillxxx 和子项的 parent.width * 0.8不能一起出现即可。

http://www.lryc.cn/news/2398859.html

相关文章:

  • UE5打包项目设置Project Settings(打包widows exe安装包)
  • Python中os模块详解
  • 便捷高效能源服务触手可及,能耗监测系统赋能智能建筑与智慧城市
  • Kotlin List 操作全面指南
  • C++--范围for循环详解
  • ISO18436-2 CATII级振动分析师能力矩阵
  • deepseek问答:torch.full() 函数详解
  • dvwa4——File Inclusion
  • MYSQL 高级 SQL 技巧
  • Spring Boot养老院管理系统源码分享
  • go|context源码解析
  • 如何在PowerBI中使用Analyze in Excel
  • 【学习记录】Element UI导入报错 * element-ui/lib/theme-chalk/index.css in ./src/main.js
  • 大模型分布式训练笔记(基于accelerate+deepspeed分布式训练解决方案)
  • 鸿蒙UI开发——组件的自适应拉伸
  • 鸿蒙仓颉语言开发教程:自定义弹窗
  • meilisearch docker 简单安装
  • Python 数据分析与可视化实战:从数据清洗到图表呈现
  • 机器学习数据降维方法
  • uefi和legacy有什么区别_从几方面分析uefi和legacy的区别
  • Spring @Autowired自动装配的实现机制
  • Neo4j 数据可视化与洞察获取:原理、技术与实践指南
  • 一种基于性能建模的HADOOP配置调优策略
  • 【Stable Diffusion 1.5 】在 Unet 中每个 Cross Attention 块中的张量变化过程
  • MySQL - Windows 中 MySQL 禁用开机自启,并在需要时手动启动
  • 前端下载文件,文件打不开的问题记录
  • 小白的进阶之路系列之十一----人工智能从初步到精通pytorch综合运用的讲解第四部分
  • OpenCV CUDA模块霍夫变换------在 GPU 上执行概率霍夫变换检测图像中的线段端点类cv::cuda::HoughSegmentDetector
  • 详解一下RabbitMQ中的channel.Publish
  • 硬件学习笔记--62 MCU的ECC功能简介