QML ListView方法positionViewAtEnd()完全相反 [英] QML ListView method positionViewAtEnd() does exactly the opposite

查看:906
本文介绍了QML ListView方法positionViewAtEnd()完全相反的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我快疯了.我在ScrollView中有一个ListView,它连接到继承QAbstractListModel的模型.将对象添加到模型后,ListView使用委托显示它们.到目前为止,一切都很好.

I'm going crazy. I have a ListView inside a ScrollView, hooked up to a model that inherits QAbstractListModel. When objects are added to the model, the ListView shows them using a delegate. So far, so good.

但是我真的希望视图一直滚动到底部(如聊天窗口),而要实现这一点非常困难.这是相关的QML代码:

But I really want the view to stay scrolled to the bottom (like a chat window), and I'm having a very difficult time making that happen. Here is the relevant QML code:

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(),它说:

The really strange thing, is that messageList.positionViewAtEnd() (at the end of the file) actually jumps it to the beginning. Without the call, the view stays where it is, even as new entries appear in the list. And indeed, if you look at the Qt documentation for the ListView.positionViewAtEnd(), it says:

考虑到...

Positions the view at the beginning or end, taking into account ...

是文档中的一个愚蠢错误,还是什么?我已经尽我所能来做所有事情,尤其是positionViewAtIndex()方法,并使用荧光笔强制滚动发生.但是没有任何效果.注意上面的源代码中的/* This works. */注释.启用该功能后,它将完全正常! (当然,它跳到ListView.count()-2索引,而不是列表的末尾)

Is that a silly error in the documentation, or what? I've tried everything I can think of to make this work, particularly the positionViewAtIndex() method and using highlighters to force the scroll to happen. But nothing works. Note the /* This works. */ comment in the source code above. When that is enabled, it works totally fine! (except of course, it jumps to the ListView.count()-2 index, instead of the end of the list)

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

Does anyone have any idea what might be wrong here? Any examples I could try to prove that there's a terrible, terrible bug in QML?

我正在将Qt 5.3.1与QtQuick 2.0一起使用(或者2.1或2.2也失败了).我也尝试了许多其他配置和代码,因此请询问是否需要更多信息.我已经完全用尽了Google-fu.

I'm using Qt 5.3.1 with QtQuick 2.0 (or 2.1 or 2.2 fail too). I've tried many, many other configurations and code as well, so please ask if you need more info. I've completely exhausted my google-fu.

谢谢!

编辑1

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

While the accepted answer does solve the above problem, it involves adding the Component.onCompleted to the delegate. This seems to cause problems when you scroll the list, because (I believe) the delegates are added to the view when you scroll up, causing the onCompleted trigger to be called even if the model item isn't new. This is highly undesirable. In fact, the application is freezing when I try to scroll up and then add new elements to the list.

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

It seems like I need a model.onAdd() signal instead of using the existence of a delegate instance to trigger the scroll. Any ideas?

编辑2

这怎么不起作用?

    ListView {
        id: messageList
        model: textMessageFiltered
        delegate: messageDelegate

        onCountChanged: {
            console.log("This prints properly.")
            messageList.positionViewAtEnd()
        }
    }

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

The text "This prints properly" prints, so why doesn't it position? In fact, it appears to reset the position to the top. So I tried positionViewAtBeginning(), but that did the same thing.

我完全被困住了.感觉像个虫子.

I'm totally stumped. It feels like a bug.

推荐答案

您还需要设置currentIndex.

testme.qml

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++)})
        }
    }
}

仍有一些元素跳到第一个元素,然后又跳回一秒.

There is still some jumping to the first element and jumping back down for a fraction of a second.

这篇关于QML ListView方法positionViewAtEnd()完全相反的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆