我要疯了。我在 ScrollView 中有一个 ListView,连接到一个继承 QAbstractListModel 的模型。当对象被添加到模型中时,ListView 使用委托显示它们。到目前为止,一切都很好。
但我真的希望视图保持滚动到底部(就像聊天窗口一样),而且我很难做到这一点。这是相关的 QML 代码:
Rectangle {
ScrollView {
[anchor stuff]
ListView {
id: messageList
model: textMessageFiltered
delegate: messageDelegate
}
}
TextField {
id: messageEditor
[anchor stuff]
onAccepted: {
controller.sendTextMessage(text)
text = ""
/* This works. */
//messageList.positionViewAtEnd();
}
}
Component {
id: messageDelegate
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
color: "white"
height: nameText.height + 4
Text {
id: nameText
wrapMode: Text.Wrap
text: "<b>" + authorName + " (" + authorId + ")</b> " + message
[anchor stuff]
}
ListView.onAdd: {
console.log("This prints just fine!")
messageList.positionViewAtEnd()
}
}
}
}
真正奇怪的是messageList.positionViewAtEnd()
(在文件末尾)实际上将其跳转到开头。如果没有调用,视图将保持在原来的位置,即使新条目出现在列表中也是如此。事实上,如果你查看ListView.positionViewAtEnd() 的 Qt 文档,它会说:
将视图定位在开头或结尾,考虑到...
这是文档中的愚蠢错误,还是什么?我已经尝试了我能想到的一切来完成这项工作,特别是positionViewAtIndex()
使用荧光笔强制滚动发生的方法和使用荧光笔。但没有任何效果。注意/* This works. */
上面源代码中的注释。启用后,它工作得很好!(当然,除了它跳转到 ListView.count()-2 索引,而不是列表的末尾)
有谁知道这里可能出了什么问题?我可以尝试证明 QML 中有一个可怕的、可怕的错误的任何例子吗?
我将 Qt 5.3.1 与 QtQuick 2.0 一起使用(或者 2.1 或 2.2 也失败了)。我也尝试了很多很多其他配置和代码,所以请询问您是否需要更多信息。我已经完全用尽了我的 google-fu。
谢谢!
编辑 1
虽然接受的答案确实解决了上述问题,但它涉及将 添加Component.onCompleted
到委托中。当您滚动列表时,这似乎会导致问题,因为(我相信)当您向上滚动时,代表会添加到视图中,即使模型项不是新的,也会导致调用 onCompleted 触发器。这是非常不希望的。事实上,当我尝试向上滚动然后向列表中添加新元素时,应用程序会冻结。
似乎我需要一个 model.onAdd() 信号,而不是使用委托实例的存在来触发滚动。有任何想法吗?
编辑 2
这怎么行?
ListView {
id: messageList
model: textMessageFiltered
delegate: messageDelegate
onCountChanged: {
console.log("This prints properly.")
messageList.positionViewAtEnd()
}
}
文本“这打印正确”打印,为什么它不定位?实际上,它似乎将位置重置为顶部。所以我尝试positionViewAtBeginning()
了,但做了同样的事情。
我完全被难住了。感觉是个bug。