QML ListView方法positionViewAtEnd()完全相反

jmb*_*eck 16 qt listview qml qt5.3

我要疯了.我在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()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

真正奇怪的是,messageList.positionViewAtEnd()(在文件的末尾)实际上将它跳到了开头.如果没有调用,视图将保持原样,即使列表中出现新条目也是如此.事实上,如果您查看ListView.positionViewAtEnd()Qt文档,它会说:

将视图定位在开头或结尾,同时考虑到......

这是文档中的愚蠢错误,还是什么?我已经尝试了所有我能想到的工作,特别是positionViewAtIndex()方法和使用荧光笔强制滚动发生.但没有任何作用.请注意/* This works. */上面源代码中的注释.当启用它时,它完全正常!(当然,它跳转到ListView.count() - 2索引,而不是列表的末尾)

有谁知道这里可能有什么问题?我可以尝试证明QML中有一个可怕的,可怕的错误的任何例子?

我正在使用Qt 5.3.1和QtQuick 2.0(或2.1或2.2也失败).我已经尝试了很多很多其他配置和代码,所以请询问您是否需要更多信息.我已经完全用尽了谷歌.

谢谢!


编辑1

虽然接受的答案确实解决了上述问题,但它涉及向Component.onCompleted委托添加.当您滚动列表时,这似乎会导致问题,因为(我相信)向上滚动时会将代理添加到视图中,从而导致调用onCompleted触发器,即使模型项不是新项也是如此.这是非常不受欢迎的.实际上,当我尝试向上滚动然后将新元素添加到列表时,应用程序会冻结.

看起来我需要一个model.onAdd()信号,而不是使用委托实例的存在来触发滚动.有任何想法吗?


编辑2

这怎么不行?

    ListView {
        id: messageList
        model: textMessageFiltered
        delegate: messageDelegate

        onCountChanged: {
            console.log("This prints properly.")
            messageList.positionViewAtEnd()
        }
    }
Run Code Online (Sandbox Code Playgroud)

文本"打印正确"打印,所以为什么不定位?实际上,它似乎将位置重置为顶部.所以我尝试了positionViewAtBeginning(),但那做了同样的事情.

我完全难过了.感觉就像一个bug.

Sim*_*rta 7

你也需要设置它currentIndex.

testme.qml

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0

ApplicationWindow {
    title: qsTr("Hello World")
    width: 300
    height: 240

    ScrollView {
        anchors.fill: parent

        ListView {
            anchors.fill: parent

            id: messageList
            model: messageModel
            delegate: Text { text: mytextrole }
            highlight: Rectangle { color: "red" }
            highlightMoveDuration: 0

            onCountChanged: {
                var newIndex = count - 1 // last index
                positionViewAtEnd()
                currentIndex = newIndex
            }
        }
    }

    ListModel {
        id: messageModel
        ListElement { mytextrole: "Dog"; }
        ListElement { mytextrole: "Cat"; }
    }

    Timer {
        property int counter: 0
        running: true
        interval: 500
        repeat: true

        onTriggered: {
            messageModel.append({"mytextrole": "Line" + (counter++)})
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一些跳到第一个元素并跳回来几分之一秒.


mcc*_*chu 5

文档中有一个注释:

注意:只应在Component完成后调用方法.要在启动时定位视图,应该通过Component.onCompleted调用此方法.

改变你ListView.onAdd:

Component.onCompleted: {
    console.log("This prints just fine!")
    messageList.positionViewAtEnd()
}
Run Code Online (Sandbox Code Playgroud)

它运作良好.

在您的情况下,ListView add在创建和完成新委托之前发出信号.ListView仍在处理场景背后的某些事情,因此positionViewAtEnd无法按预期工作.而且/* This works. */由于新的委托完成后,它被调用.但是,不要认为这总是有效.只需按照说明,称positionViewAtEndComponent.onCompleted,在文档中.