Я схожу с ума. У меня есть ListView внутри ScrollView, подключенный к модели, которая наследует 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()
(в конце файла) фактически перескакивает его в начало. Без вызова вид остается там, где он есть, даже когда в списке появляются новые записи. И действительно, если вы посмотрите на документацию Qt для ListView.positionViewAtEnd(), в нем говорится:
Позиционирует представление в начале и конце , принимая во внимание...
Это глупая ошибка в документации или что? Я пробовал все, что мог придумать, чтобы сделать эту работу, особенно метод 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()
}
}
Текст "Отпечатывается правильно" печатает, так почему же он не позиционируется? На самом деле, как представляется, reset позиция сверху. Поэтому я попробовал positionViewAtBeginning()
, но сделал то же самое.
Я полностью в тупике. Это похоже на ошибку.