Qt QML ListView-更改除当前项以外的所有项

Qt QML ListView-更改除当前项以外的所有项,qt,listview,model,qml,qtquick2,Qt,Listview,Model,Qml,Qtquick2,我在使用Qt5.7和QtQuick 2.0时,正在学习Qt4.8的教程(每个条目中没有flickable内容)。列表视图的工作方式如下所示: 用户单击列表中的项目 显示项目的备选(详细)视图 用户必须单击详细视图中的Close按钮,将条目状态重置为默认的紧凑视图 这会导致混乱,如果用户单击所有项目,在某种情况下,所有项目都将显示在其完整视图中。让用户在每次打开详细视图时单击Close按钮也不是那么方便 我已将条目更改为在用户单击视图时关闭。我还试图防止这种混乱,并实现更流畅的行为: 用户单击列表

我在使用Qt5.7
QtQuick 2.0
时,正在学习Qt4.8的教程(每个条目中没有flickable内容)。
列表视图的工作方式如下所示:

  • 用户单击列表中的项目
  • 显示项目的备选(详细)视图
  • 用户必须单击详细视图中的
    Close
    按钮,将条目状态重置为默认的紧凑视图
  • 这会导致混乱,如果用户单击所有项目,在某种情况下,所有项目都将显示在其完整视图中。让用户在每次打开详细视图时单击
    Close
    按钮也不是那么方便

    我已将条目更改为在用户单击视图时关闭。我还试图防止这种混乱,并实现更流畅的行为:

  • 用户单击列表中的项目
  • 将显示项目的备选视图
  • 用户单击详细视图,将条目状态重置为默认的紧凑视图
  • 用户单击另一个条目,当前详细视图中的所有条目都将重置为其压缩视图
  • 目前,我正在遍历我的
    列表视图
    contentItem.children[loop\u index]
    ,并将状态设置为
    “详细信息”
    =显示详细视图
    ”=显示压缩视图)。由于
    ListView
    的工作方式(按需加载/卸载代理),这是非常不可靠的,当我尝试访问其他代理的状态时,我经常会得到一个未定义的引用。下面的
    MouseArea
    ,我用它来做所有这些,是每个代表的一部分:

    // state is a QML `State` that is bound to the delegate (see below for the details on it)
    MouseArea {
        anchors.fill: background
        onClicked: {
            // Iterate through all other entries and close them
            for (var entry = 0; entry < listView.count; ++entry) {
                if(listView.contentItem.children[entry] !== gestureEntry) {
                    console.log("Hide other element");
                    listView.contentItem.children[entry].state = ""; // IT FAILS HERE (SOMETIMES)
                }
            }
    
            // Change view of current entry
            if(gestureEntry.state === "Details") {
                gestureEntry.state = "";
                console.log("Hiding details")
            }
            else {
                gestureEntry.state = "Details";
                console.log("Showing details");
            }
        }
    }
    
    我认为
    状态
    信息可以存储在
    列表模型
    本身中,从而可以迭代模型的内容(与代理的内容不同,这些内容总是存在),但是我不知道如何自动更新我的列表(以及当前可见/不可见的代理)当模型中的条目发生更改时。从我目前发现的情况来看,这似乎是不可能的,因为
    ListView
    没有主动监视它的
    ListModel


    真的是这样吗?如果是,那么是否可以用不同的方法解决此问题?

    为什么不使用
    列表视图的
    currentIndex
    属性? 只需按如下方式修改您的委托:

    Item {
        id: gestureEntry
        ...
        state: ListView.isCurrentItem?"Details":""
        ...
        MouseArea {
            anchors.fill: background
            onClicked: {
                if(listView.currentIndex == index)
                    listView.currentIndex = -1
                else
                    listView.currentIndex = index
            }
        }
    }
    
    编辑: 上述解决方案的唯一问题是,加载时,
    ListView
    中的一个条目被预选,这会自动触发该条目的详细视图。为了避免出现这种情况,需要将以下内容添加到
    列表视图中:

    Component.onCompleted: {
        listView.currentIndex = -1;
    }
    

    这确保不会预选任何条目。

    我想这是一个问题,因为您在代理中存储了状态。您不应该像
    委托
    -property()中所述那样执行此操作,因为委托离开视图时会被重用

    当:ListView.isCurrentItem
    处于状态并依赖于ListView的值时,至少应该使用
    。因此,只有您当前的代理被最大化。然后在MouseArea中只设置'ListView.view.currentIndex=index'不要在功能中手动更改状态

    我也遇到了同样的问题,完全删除了状态,只使用了附加的属性
    ListView.iscurrentem
    。但是将状态绑定到ListView中的值也应该起作用,因为它不存储在委托中

    最简单的例子:

    import QtQuick 2.0
    
    Item {
        width: 800
        height: 600
    
        ListView {
            id: view
            anchors.fill: parent
            model: 3
            spacing: 5
            currentIndex: -1
            delegate: Rectangle {
                id: delegate
                color: ListView.isCurrentItem ? "lightblue" : "green" // directly change properties depending on isCurrentItem
                height: 100
                width: 100
    
                states: State {
                    name: "maximized"
                    when: delegate.ListView.isCurrentItem // bind to isCurrentItem to set the state
                    PropertyChanges {
                        target: delegate
                        height: 200
                    }
                }
                MouseArea {
                    anchors.fill: parent
                    //onClicked: delegate.ListView.view.currentIndex = model.index // if only selection is wanted
                    onClicked: {
                        //console.debug("click");
                        if (delegate.ListView.isCurrentItem)
                        {
                            delegate.ListView.view.currentIndex = -1;
    
                        }
                        else
                        {
                            delegate.ListView.view.currentIndex = model.index;
                        }
                    }
                }
                Text {
                    anchors.centerIn: parent
                    text: index
                }
            }
            Text {
                text: "CurrentIndex: " + parent.currentIndex
            }
        }
    }
    

    我在
    ListView.view.currentIndex=index处得到一个
    TypeError
    我还尝试将其更改为
    listView.view.currentIndex=index(因为我的
    ListView
    具有该ID,但问题仍然存在。ListView会像索引一样附加到您的代理根项。也许您必须显式使用
    delegateId.ListView.currentIndex=delegateId.index
    。甚至在代理中调用一个信号,它应该可以工作。我已经使用了很多次,而且确实可以工作这里,使用Qt 5.5.1.
    gestureEntry
    gestureDelegate
    中的
    项,它是我的
    ListView
    委托中使用的
    组件e> 第一次出现的问题是,用户在单击所选条目时无法更改回压缩视图。啊,等等。现在,单击条目后关闭不起作用…XD我实际上需要
    if-else
    内部
    onClicked
    。这打破了您的解决方案。:-/编辑了我的答案。希望这将我这次工作:)剩下的唯一问题是第一次加载
    ListView
    时,第一个条目(我猜加载列表时预选的条目)在详细视图中。修复了它。添加了
    Component.onCompleted:{ListView.currentIndex=-1;}
    ,以避免预选条目。
    import QtQuick 2.0
    
    Item {
        width: 800
        height: 600
    
        ListView {
            id: view
            anchors.fill: parent
            model: 3
            spacing: 5
            currentIndex: -1
            delegate: Rectangle {
                id: delegate
                color: ListView.isCurrentItem ? "lightblue" : "green" // directly change properties depending on isCurrentItem
                height: 100
                width: 100
    
                states: State {
                    name: "maximized"
                    when: delegate.ListView.isCurrentItem // bind to isCurrentItem to set the state
                    PropertyChanges {
                        target: delegate
                        height: 200
                    }
                }
                MouseArea {
                    anchors.fill: parent
                    //onClicked: delegate.ListView.view.currentIndex = model.index // if only selection is wanted
                    onClicked: {
                        //console.debug("click");
                        if (delegate.ListView.isCurrentItem)
                        {
                            delegate.ListView.view.currentIndex = -1;
    
                        }
                        else
                        {
                            delegate.ListView.view.currentIndex = model.index;
                        }
                    }
                }
                Text {
                    anchors.centerIn: parent
                    text: index
                }
            }
            Text {
                text: "CurrentIndex: " + parent.currentIndex
            }
        }
    }