QML 阻止 ListView 委托一直更新

Posted

技术标签:

【中文标题】QML 阻止 ListView 委托一直更新【英文标题】:QML prevent ListView delegate to update all the time 【发布时间】:2020-07-31 14:59:29 【问题描述】:

我对 QML/QtQuick 比较陌生,并且还在学习。我对一个非常小的私人项目有一点性能问题。我只是尝试在我的 ListView 中实现一个过滤器功能,因为 >15.000 个对象需要手动搜索很多。当我完成搜索字段的编辑或按“返回”时,我只想更新 ListView。但是每次我从这个文本字段中插入或删除一个字符时,它都会刷新,有时需要几秒钟。

有人知道如何防止列表永久刷新或减少这些性能问题吗?

非常感谢

import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.XmlListModel 2.12
import Anime_initialiser  1.0
import "."

Page 
    TextField
        id: searchField
        width: parent.width
        z: 1
        /*onEditingFinished: 
            XL.animeListModel.reload()
        */
    
    ListView 
        z: 0
        ScrollBar.vertical: ScrollBar  active: true 
        id: listView
        width: parent.width
        height: parent.height
        model: XL.animeListModel
        y: searchField.height
        Anime_initialiser 
            id: initialiser
            onShowAnimeDetails: 
                xmlDataString = xmlString
                swipeView.currentIndex = swipeView.currentIndex+1
            
        
        delegate: ItemDelegate 
            visible: 
                if (searchField.length > 0)
                    return (main_title.toLowerCase().match(searchField.text.toLowerCase()) || de_title.toLowerCase().match(searchField.text.toLowerCase())) ? true : false
                else
                    return true
            
            height:  visible ? Button.height : 0
            width: parent ? parent.width : 0
            Button 
                anchors.fill: parent
                onClicked: 
                    anime_id = aid
                    initialiser.buttonClicked(anime_id)
                
                Text 
                    width: parent.width
                    height: parent.height
                    font.pointSize: 100
                    minimumPointSize: 12
                    fontSizeMode: Text.Fit
                    text: aid + ": " + main_title + (de_title ? "\nDE: " + de_title : "")
                
            
        
    

【问题讨论】:

【参考方案1】:

您应该使用QSortFilterProxyModel,而不是切换所有代表的可见标志。这个想法是代理模型将使用您的XL.animeListModel 作为源模型,然后您可以给代理一个正则表达式,告诉它​​要过滤掉哪些。根据您希望它过滤的方式,您可以调用setFilterRole() 告诉它要与您的正则表达式比较哪个属性,或者您可以通过覆盖filterAcceptsRow() 函数来执行自定义过滤器。

编辑

如果您不想使用代理,您仍然可以通过不将visible 属性直接绑定到搜索字段来防止常量更新。您的onEditingFinished 代码走在了正确的轨道上。您可以创建一个单独的文本字符串来保存完整的搜索文本。

property string searchText: ""

然后在您输入完搜索文本后更新该字符串。

onEditingFinished: 
    searchText = searchField.text.toLowerCase();

最后,将您的 visible 属性绑定到这个新字符串。

            visible: 
                if (searchText.length > 0)
                    return (main_title.toLowerCase().match(searchText) || de_title.toLowerCase().match(searchText)) ? true : false
                else
                    return true
            

【讨论】:

谢谢,我看到了几篇包含“QSortFilterProxyModel”的帖子,但我想我可以通过这种方式解决它。即便如此,我真的很想了解 QML 为何这样做。我认为列表会被渲染一次,并且不会在没有直接调用的情况下更新。您(或其他任何人)是否知道并可以向我解释为什么会发生这种情况? 您已将代理的 visible 属性绑定到 searchField.text。每次该文本更改时,它都会重新评估 visible。我可以在我的答案中添加一个编辑,向您展示如何解决这个问题。 如果您有时间并且喜欢这样做,那将非常好,但您不必这样做。只是多了解一点 QML。但即使它只是一个私人项目,我也会尝试使用 QSortFilter 以干净的方式完成它。到目前为止,你帮了我很多,谢谢。

以上是关于QML 阻止 ListView 委托一直更新的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++ 访问 QML ListView 委托项目?

QML ListView隐藏的委托项

QML ListView 访问委托的项目

如何外包 qml listview 委托

从 QML ListView 委托调用 JavaScript 对象方法

如何在 QML 中访问 ListView 的 ListModel 的 ListElement 的映射委托数据?