跳转到内容
新建笔记

QML 锚点与边距:约束、目标和布局边界

锚点把一个项目的边缘、中心线或基线与另一个项目的锚线建立关系。它持续响应相关几何变化,适合表达“位于标题下方”“距父项右边 16 像素”等约束。本文按 Qt 6.10 说明;anchors 属于 QtQuick.Item,不是只在某一种矩形控件上可用。

可用锚线包括 left、right、top、bottom、horizontalCenter、verticalCenter 和 baseline。anchors.centerIn 同时居中两个方向;anchors.fill 把四边锚到目标四边。

锚点目标必须是该项目的父项或兄弟项目,不能任意跨越对象树。也不要求所有锚点指向同一个目标:左边锚到父项、右边锚到一个兄弟项是合法的,只要同一方向的约束不冲突。水平锚线连接水平对应位置,垂直锚线连接垂直对应位置,不能把 left 接到 top。

约束结果或限制
左边与右边都锚定由两端位置确定宽度;不再同时用另一套逻辑控制 x、width
只锚左边可另外指定宽度;没有覆盖垂直方向的 y、height
顶边与底边都锚定由两端位置确定高度
水平居中可另外指定宽度;不要再加同方向的两侧约束
baseline用于对齐文本基线;不要与矛盾的顶、底或垂直中心约束同时使用

所以“使用锚点就不能写任何位置或尺寸属性”过于绝对。应按方向判断:水平已由左右锚决定时,不要再控制水平几何;只约束水平不会自动禁止垂直定位。

边距、偏移与不同目标

跳转到“边距、偏移与不同目标”

保存为 AnchorsDemo.qml。面板右侧与兄弟侧栏保持间隔,左侧跟随父项;标题下的内容随标题高度改变位置。

import QtQuick
Item {
id: root
width: 480
height: 300
Rectangle {
id: sidebar
width: 100
color: "#d9e2ec"
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.margins: 16
}
Rectangle {
id: panel
color: "#f0d7b5"
anchors.left: parent.left
anchors.right: sidebar.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: 16
anchors.rightMargin: 12
anchors.topMargin: 16
anchors.bottomMargin: 16
Text {
id: title
text: "Anchors"
font.pixelSize: 24
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 12
}
Rectangle {
id: content
color: "#fffaf3"
anchors.top: title.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 12
}
}
}

anchors.margins 是已建立边缘锚点的统一边距;没有锚到某一边时,对应边距不凭空建立约束。单边的 leftMargin 等可以覆盖统一值。中心与基线使用 horizontalCenterOffset、verticalCenterOffset、baselineOffset;中心偏移不通过 margins 调整。

Grid 的外边距不会拉伸内部子项

跳转到“Grid 的外边距不会拉伸内部子项”

下面保留原稿的四格场景。Grid 填满父项减去边距后的区域,但四个矩形各自仍为 80×50。spacing 只设置格子之间的间隔,不把它们平均放大。保存为 GridMargins.qml:

import QtQuick
Item {
width: 300
height: 200
Grid {
id: grid
anchors.fill: parent
anchors.margins: 20
columns: 2
spacing: 10
Rectangle { width: 80; height: 50; color: "red" }
Rectangle { width: 80; height: 50; color: "green" }
Rectangle { width: 80; height: 50; color: "blue" }
Rectangle { width: 80; height: 50; color: "yellow" }
}
}

需要分配剩余空间时可选 QtQuick.Layouts 的 GridLayout、RowLayout、ColumnLayout,通过 Layout.fillWidth、Layout.preferredWidth 等表达尺寸意图。布局拥有其子项的几何控制权,子项不要再与布局同时争用 anchors、x、y、width、height。Grid、Row、Column 是定位器,与这些布局类型也不是同一个接口。

切换左右锚时,先取消旧约束再建立新约束,避免短暂出现“两边都被锚定”而拉伸宽度。声明式状态切换可用 AnchorChanges,边距则由 PropertyChanges 改变,配合 AnchorAnimation 做锚点过渡。不要依赖多个属性绑定的求值顺序来解除冲突。

遇到位置错误,先检查目标是否为父项或兄弟项,再检查同一轴有没有重复约束,最后确认尺寸是否由定位器、布局或另外的绑定控制。锚点只能处理几何关系,不能自动解决内容隐式大小、文本换行或滚动区域范围。

语义依据:Qt 6.10 锚点定位、Item anchors 属性、Qt Quick Layouts 概览。