我创建了一个对象树,树是使用非常简单的逻辑绘制的:
- 每个对象都与它自己的表示加上它的孩子(以及他们的孩子等等......)的表示一样大
- 如果对象是其父对象的第一个子对象,则在其视觉表示下缩进绘制
- 每个下一个对象都直接绘制在它的前一个兄弟之下
但是,在某些情况下插入新对象时,这种简单的算法会失败。例如:
在这种情况下,节点 1 和 2 成功插入到节点 0 中,节点 0 的全高(每个节点左侧的黑线)是它自己的 UI 加上它的两个子节点的总和。
但是当节点 3 插入节点 1 时,布局中断 - 节点 2 没有被下推,结果它与新插入的节点重叠,使其黑线不可见。
当触发额外的刷新周期时,树会恢复正常,因此故障一定是由一些临时的“或同步”属性引起的。请注意,一次额外的刷新并不总是使树按顺序排列,这取决于插入的位置,有时该错误可能需要几个刷新周期才能“级联”掉干扰对齐。
有什么想法可能导致这种不稳定的行为和/或如何解决它?是什么导致代码偶尔中断,为什么即使它最终可以工作,它也需要一到多次刷新才能使自己井井有条?
编辑:我已经能够隔离并查明对齐何时中断 - 当插入到未结束其级别上的最后一个节点的节点时。只要每个新节点都插入到最后一个并且“打开”的节点中,所有绑定都会正确传播,例如在该级别上没有下一个节点,但是插入任何先前的节点都会破坏绑定。因此,需要额外的刷新周期来逐步消除它影响的所有级别的错误。但我仍然不知道是什么原因导致它以及如何修复它,只有当它发生时。
编辑:再调查一下,似乎在将新子项插入父项并根据其顺序重新对齐其子项后,父项的childrenRect
属性不会立即反映大小的变化。因此,当插入对象的下一个兄弟对象被定位时,它仍然使用旧的过时值作为对象高度,这不会影响新插入的对象,因为它不使用它。所以我想下一个大问题是如何修复它,以便绑定发生,以便算法可以按预期使用正确的数据?我尝试使用计时器来延迟操作,但它似乎不是时间问题,而是关于逻辑顺序的问题,例如,它当前需要的刷新计数以消除等于它发生的部门的错误。
编辑:我想出了如何“解决它”但是......不是真的,我仍然不知道是什么原因导致它以及如何避免它,但是比更新整个树直到它被修复更“经济”的解决方案去父母那里,只更新当前分支,直到到达根目录。这确实节省了很多,但我仍然希望立即拥有正确的值,因为绑定应该可以工作,至少 IMO 是这样。
编辑:这是订购代码:
for (int i = 0; i < _children.size(); ++i) {
UI * ui = _children.at(i)->_ui;
if (ui) {
if (i) {
UI * prev = _children.at(i-1)->_ui;
ui->setX(prev->x());
ui->setY(prev->height() + prev->y());
} else {
ui->setX(Object::_helper->nodeSize());
ui->setY(_ui->childOffset());
}
}
}
以及如何设置 QML 的示例:
UI {
id: main
width: childrenRect.width
height: childrenRect.height
Item {
height: childrenRect.height
Rectangle {
width: Helper.nodeSize
height: Helper.nodeSize
color: "red"
Text {
anchors.centerIn: parent
text: main.id
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.RightButton)
Helper.gotoXY(main.absolutePosition())
else {
Helper.createObject(1, main)
Helper.updateRoot()
}
}
Rectangle {
height: main.height
width: 10
x: -10
color: "black"
}
}
}
}
}