QML ListView - 更改除当前项目以外的所有项目
QML ListView - change all but current item
我在使用 Qt 5.7[=55= 时正在关注 Qt 4.8 的 this 教程(每个条目中没有可滑动的内容) ] 与 QtQuick 2.0
。 ListView
的工作方式如下:
- 用户点击列表中的项目
- 显示项目的替代(详细)视图
- 用户必须在详细视图中单击
Close
按钮才能将条目状态重置为其默认的紧凑视图。
这会导致混乱,在某些时候,如果用户单击所有项目,在这种情况下,所有项目都会以完整视图显示。每次 he/she 打开详细视图时让用户单击 Close
按钮也不是那么方便。
我已将条目更改为在用户单击视图时关闭。我也在努力防止这种混乱并实现更(omho)流动的行为:
- 用户点击列表中的项目
- 显示项目的替代视图
- 用户单击详细视图以将条目状态重置为其默认的紧凑视图或
- 用户单击另一个条目,所有当前在详细视图中的条目都将重置为其紧凑视图
目前我正在遍历 ListView
的 contentItem.children[loop_index]
并将状态设置为 ""
("Details"
= 显示详细视图 | ""
= 显示紧凑视图)。由于 ListView
的工作方式(loading/unloading 按需委托),这是非常不可靠的,当我尝试访问其他委托的状态时,我经常得到未定义的引用。以下 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");
}
}
}
其中 state
是代表的状态:
states: State {
name: "Details"
PropertyChanges { target: background; color: "white" }
PropertyChanges { target: gestureImage; width: 130; height: 130 } // Make picture bigger
PropertyChanges { target: gestureEntry; detailsOpacity: 1; x: 0; y: 0 } // Make details visible
PropertyChanges { target: gestureEntry; height: listView.height } // Fill the entire list area with the detailed view
}
我认为 state
信息可以存储在 ListModel
本身中,从而可以遍历模型的内容(与委托的内容不同,它们始终存在)我不知道如何在模型中的条目更改时自动更新我的列表(以及当前的 visible/invisible 代表)。到目前为止我发现似乎不可能这样做,因为 ListView
没有主动监控它的 ListModel
.
真的是这样吗?如果是,那么是否可以用不同的方式解决这个问题?
为什么不使用 ListView
的 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
中的条目,这会自动触发该条目的详细视图。为了避免需要在 listView
中添加以下内容:
Component.onCompleted: {
listView.currentIndex = -1;
}
这确保不会预选任何条目。
我猜这是一个问题,因为您在委托中存储了一个状态。您不应按照 delegate
-属性 (Link) 中的描述执行此操作,因为委托在离开视图时会被重用。
至少你应该在 State 中使用一个 when: ListView.isCurrentItem
并依赖于 ListView 的一个值。所以只有你当前的委托被最大化。然后在 MouseArea 中只设置 `ListView.view.currentIndex = index'。 不要在函数中手动改变状态!
我运行遇到了同样的麻烦,完全删除了状态,只使用了附件属性ListView.isCurrentItem
。但是将状态绑定到 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
}
}
}
我在使用 Qt 5.7[=55= 时正在关注 Qt 4.8 的 this 教程(每个条目中没有可滑动的内容) ] 与 QtQuick 2.0
。 ListView
的工作方式如下:
- 用户点击列表中的项目
- 显示项目的替代(详细)视图
- 用户必须在详细视图中单击
Close
按钮才能将条目状态重置为其默认的紧凑视图。
这会导致混乱,在某些时候,如果用户单击所有项目,在这种情况下,所有项目都会以完整视图显示。每次 he/she 打开详细视图时让用户单击 Close
按钮也不是那么方便。
我已将条目更改为在用户单击视图时关闭。我也在努力防止这种混乱并实现更(omho)流动的行为:
- 用户点击列表中的项目
- 显示项目的替代视图
- 用户单击详细视图以将条目状态重置为其默认的紧凑视图或
- 用户单击另一个条目,所有当前在详细视图中的条目都将重置为其紧凑视图
目前我正在遍历 ListView
的 contentItem.children[loop_index]
并将状态设置为 ""
("Details"
= 显示详细视图 | ""
= 显示紧凑视图)。由于 ListView
的工作方式(loading/unloading 按需委托),这是非常不可靠的,当我尝试访问其他委托的状态时,我经常得到未定义的引用。以下 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");
}
}
}
其中 state
是代表的状态:
states: State {
name: "Details"
PropertyChanges { target: background; color: "white" }
PropertyChanges { target: gestureImage; width: 130; height: 130 } // Make picture bigger
PropertyChanges { target: gestureEntry; detailsOpacity: 1; x: 0; y: 0 } // Make details visible
PropertyChanges { target: gestureEntry; height: listView.height } // Fill the entire list area with the detailed view
}
我认为 state
信息可以存储在 ListModel
本身中,从而可以遍历模型的内容(与委托的内容不同,它们始终存在)我不知道如何在模型中的条目更改时自动更新我的列表(以及当前的 visible/invisible 代表)。到目前为止我发现似乎不可能这样做,因为 ListView
没有主动监控它的 ListModel
.
真的是这样吗?如果是,那么是否可以用不同的方式解决这个问题?
为什么不使用 ListView
的 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
中的条目,这会自动触发该条目的详细视图。为了避免需要在 listView
中添加以下内容:
Component.onCompleted: {
listView.currentIndex = -1;
}
这确保不会预选任何条目。
我猜这是一个问题,因为您在委托中存储了一个状态。您不应按照 delegate
-属性 (Link) 中的描述执行此操作,因为委托在离开视图时会被重用。
至少你应该在 State 中使用一个 when: ListView.isCurrentItem
并依赖于 ListView 的一个值。所以只有你当前的委托被最大化。然后在 MouseArea 中只设置 `ListView.view.currentIndex = index'。 不要在函数中手动改变状态!
我运行遇到了同样的麻烦,完全删除了状态,只使用了附件属性ListView.isCurrentItem
。但是将状态绑定到 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
}
}
}