下面的代码有两个问题。
如果我在QML列中使用padding,我会收到以下消息:
QML列:可能的QQuickItem::polish()循环
并且应用程序变得无响应。另外,如果我不使用锚点,问题就不会出现,但列中的矩形不会被拉伸。
如果我使用锚点,列的implicitWidth和impliciHeight将为零,这将导致矩形不会显示。
Qt文档是这样写的:
此外,由于列自动垂直定位其子项,因此列中的子项不应设置其y位置,也不应使用top、bottom、anchors.verticalCenter、fill或centerIn锚点垂直锚定自身。
这意味着水平锚定(左/右)不被禁止。
你知道会出什么问题吗?
Rectangle {
anchors.fill: parent
color: "green"
Rectangle {
anchors.centerIn: parent
implicitWidth: col.implicitWidth
implicitHeight: col.implicitHeight
color: "blue"
Column {
spacing: 10
//padding: 10 // causes: QML Column: possible QQuickItem::polish() loop
id: col
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
implicitWidth: 100
implicitHeight: 25
}
Rectangle {
//anchors.left: parent.left // uncommenting these anchors will result that the column's implicitWidth and implicitHeight will be 0
//anchors.right: parent.right
implicitWidth: 200
implicitHeight: 25
}
Component.onCompleted: console.log("column, imp width: " + implicitWidth + ", imp height: " + implicitHeight)
}
}
}
发布于 2021-02-28 05:14:36
正如评论中所讨论的,
的代码可以改进:
删除父子关系,改为创建一个新的默认属性别名,如下所示:
Rectangle
{
default property alias data2: col.data
data:
[
Column
{
id: col;
onChildrenChanged: { ...calculate sizes, add bindings, etc... }
}
]
}
它是如何工作的:
在QML代码中将对象嵌套在另一个对象中时,是将它们添加到标记为
父对象内部
对于
因此
名为
标记为
该属性包含可视化子级和资源的组合列表。
/
因此,通常将可视元素嵌套在
导致它们被添加为
的视觉子对象
所以通常
..。
...is相当于:
我通过创建一个名为
并将其设置为
对于
与
因此它的元素不会被添加到
的可视化子项列表
取而代之的是我做了
的别名
属性
一个
属性只是属性的别名,在本例中是属性的另一个名称,作为另一个对象的属性,但这两个名称都“指向”相同的实际属性,因此
的可视化子项列表
所以所有QML元素都嵌套在
被添加为
但是,现在我有一个问题:我不能仅仅嵌套
变成
QML代码,因为这意味着
需要添加为它自己的子项(这没有任何意义)
所以我必须分配
的实际
属性(它不再是默认的,所以我必须显式地写出它的名称),因此添加了
作为
现在,无论何时
的嵌套元素被添加或移除(包括通过
)、
%s
属性的更改,但由于我们添加的是可视子级
属性也会发生更改。
因此,我们可以在以下情况下触发重新计算和重新绑定
%s
信号触发(或
如果您还想在非可视子对象上触发(也称为
)
您可以跳过已具有绑定的元素,也可以仅重新绑定它们
据我所知,这应该是有效的和受支持的QML语法-只是不是您通常使用的语法-所以在生产代码中使用它是可以的,可能会有一个注释来解释正在发生的事情
发布于 2021-02-23 07:40:37
填充
将元素附加到列的左边缘和右边缘,然后告诉列应该将其元素放置在距该边界10个像素的位置。
然后,它们开始通过各自导致布局更新并触发彼此来“打架”。
您需要放置一个中间元素来处理填充,如下所示:
Column{ padding: 10; Column{ id: col; Rectangle{}; Rectangle{}; } }
锚
让我们来看看到底发生了什么
我在每个元素中插入了一些调试代码:
property string name: "..."//I named them: "green_rect", "blue_rect", "col", "top_rect", "bottom_rect"
onWidthChanged: console.log(name + " changed: w=" + width)
....
property string mydbgstr: "top_rect w=" + width + " h=" + height + " iw=" + implicitWidth + " ih=" + implicitHeight
onMydbgstrChanged: console.log(mydbgstr)
当任何属性发生更改时,它都会打印一个字符串
我的窗口是500x500
初始布局-这对于所有情况都保持不变:
// property change notifications removed since they are not interesting yet
qml: bottom_rect w=200 h=25 iw=200 ih=25
qml: top_rect w=100 h=25 iw=100 ih=25
qml: col w=0 h=0 iw=0 ih=0
qml: blue_rect w=0 h=0 iw=0 ih=0
qml: green_rect w=0 h=0 iw=0 ih=0
好了,锚点还没有被应用,列也还没有计算出它的大小,所以元素只是简单地假设h=ih w=iw
在那之后,我们看到了不同的结论:
顶部和底部矩形的锚点都评论道:
qml: col changed: w=200
qml: col changed: h=60
qml: col changed: iw=200
qml: blue_rect changed: w=200
qml: blue_rect changed: iw=200
qml: blue_rect w=200 h=0 iw=200 ih=0
qml: col changed: ih=60
qml: col w=200 h=60 iw=200 ih=60
qml: blue_rect changed: h=60
qml: blue_rect changed: ih=60
qml: blue_rect w=200 h=60 iw=200 ih=60
qml: green_rect changed: w=500
qml: green_rect w=500 h=500 iw=0 ih=0
qml: green_rect changed: h=500
结果:
▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀
按照预期工作:列根据组合子元素的大小计算其大小,然后周围的元素也假定该大小
只有top rect的锚点没有注释:
// it appears that top rect adjusted itself to fit still-zero-width column
qml: top_rect changed: w=0 col.w=0 //uh oh, top_rect is now zero-sized
qml: top_rect w=0 h=25 iw=100 ih=25
// here col probably performed layout and determined its width based on bottom rect
// however for some reason its own signal got delayed (isn't shown)
// probably because children get priority
// top_rect anchors react to column layout:
qml: top_rect changed: w=200 col.w=200 //top_rect is properly sized again
qml: top_rect w=200 h=25 iw=100 ih=25
// here col appears to react to the first layout change:
qml: col changed: w=200
qml: col changed: h=25 // height excludes top_rect which was zero-size at that point
qml: col changed: iw=200 // bottom_rect retained its size so col isn't zero-sized
//...and so surrounding elements are updated
qml: blue_rect changed: w=200
qml: blue_rect changed: iw=200
qml: blue_rect w=200 h=0 iw=200 ih=0
//...next col decides to update its implicitHeight
qml: col changed: ih=25
qml: col w=200 h=25 iw=200 ih=25
//...which causes a second layout of surroundings:
qml: blue_rect changed: h=25
qml: blue_rect changed: ih=25
qml: blue_rect w=200 h=25 iw=200 ih=25
qml: green_rect changed: w=500
qml: green_rect changed: h=500
qml: green_rect w=500 h=500 iw=0 ih=0
//This is apparently col getting the second update of top_rect:
qml: col changed: h=60 //height now includes non-zero-sized top_rect
qml: col changed: ih=60
qml: col w=200 h=60 iw=200 ih=60
//...so blue_rect is changed yet again:
qml: blue_rect changed: h=60
qml: blue_rect changed: ih=60
qml: blue_rect w=200 h=60 iw=200 ih=60
结果:
▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀
两者均未注释:
// col is zero-sized still so children cling to its zero-size
qml: bottom_rect changed: w=0 col.w=0
qml: bottom_rect w=0 h=26 iw=200 ih=26
qml: top_rect changed: w=0 col.w=0
qml: top_rect w=0 h=24 iw=100 ih=24
// because all children are zero-sized, col is also zero-sized so it doesn't attempt to do anything
// because col is zero-sized, blue_rect also remains zero-sized
qml: green_rect changed: w=500
qml: green_rect changed: h=500
qml: green_rect w=500 h=500 iw=0 ih=0
结果:绿色窗口
结论
列的宽度取决于最大的元素宽度,但是元素的宽度被锚定到列,所以它有一个鸡和蛋的问题,但是因为它是间接的,并且还会导致初始零大小持续存在,Qt无法检测到绑定循环,而是元素保持折叠。
这实际上意味着,在这种情况下,QtQuick还不够“聪明”,不能正确地定位项目。您必须指定其中一项或列的实际宽度。
更聪明一点,因为它可以指定最小、最大和首选大小,所以您可能应该使用它而不是
..。我知道你已经知道如何使用它了,所以我不会在这里详述了。
或者,命令式代码可以用来确定元素的最大宽度,并将col的宽度设置为最大宽度。如果需要,它还可以设置其他元素的宽度。
发布于 2021-02-24 00:04:23
QML列更像是一个定位器,在我的例子中,它不太适合调整其子元素的大小。
我试用了ColumnLayout,它在一定程度上解决了这个问题,但生成了很多警告消息,因为ColumnLayout不是直接的,而是从QQuickLayout派生的,其中检查锚定并转储此警告消息:“在由布局管理的项上检测到锚点。这是未定义的行为;请改用Layout.alignment。”
最后,我在QML中做了一个变通方法,它利用implicitHeight大于零的元素之间的均匀填充和间距。
它可以用作常规的QML元素。
这是根据杰克·怀特的建议修改的答案。
MyColumn.qml:
import QtQuick 2.12
Rectangle
{
default property alias data2: container.data
property int spacing: 0
property int padding: 0
implicitWidth: container.implicitWidth + 2*padding
implicitHeight: container.implicitHeight + 2*padding
data:
[
Item
{
id: container
property int spacing: parent.spacing
function implicitHeightOfChildren() {
var total = 0
for (var i=0;i max)
max = children[i].implicitWidth
return max
}
function calculateSpacing() {
var itemsWithHeight = 0
for (var i = 0; i < children.length; i++)
if(children[i].implicitHeight > 0)
itemsWithHeight++
return (itemsWithHeight > 0 ? (itemsWithHeight - 1) * spacing : 0)
}
anchors.top: parent.top
anchors.topMargin: parent.padding
anchors.left: parent.left
anchors.leftMargin: parent.padding
anchors.right: parent.right
anchors.rightMargin: parent.padding
implicitWidth: widestChild()
implicitHeight: implicitHeightOfChildren() + calculateSpacing()
onChildrenChanged:
{
for (var i=0;i 0 ? spacing : 0);
}
}
}
}
]
}
没有锚定到列的示例使用。取消对锚线的注释以查看预期行为。
MyColumn {
color: "red"
padding: 10
spacing: 10
Repeater {
model: 3
Rectangle {
//anchors.left: parent.left
//anchors.right: parent.right
implicitWidth: 100 + 25 * index
implicitHeight: 25
color: "black"
}
}
}
结果:
https://stackoverflow.com/questions/66303743
复制相似问题