【发布时间】:2012-02-20 19:24:03
【问题描述】:
一般来说,我的难题是:通过 GridView 之外的一些操作,我想仅根据之前选择的特定模型项或索引来计算 GridView 中特定委托项的坐标。
我有一个 GridView,其中包含模型中的许多项目。 GridView 的委托创建每个项目的缩略图视图。单击时,它会显示该项目的详细全屏视图。我想要一个很好的过渡,显示缩略图从它在 GridView 中的位置展开,当详细视图被关闭时,缩回到 GridView 中。
诀窍在于,详细视图本身是 ListView 的委托,因此您可以一次在一个屏幕的详细视图之间进行分页。这意味着一个简单地调整 GridView 的委托项目大小的解决方案,否则将无法正常工作。此外,由于您可以分页到 ListView 中的任何项目,因此返回到 GridView 必须仅基于模型中可用的信息或模型项目的索引(例如,我无法存储用于启动的 MouseArea 的坐标详细视图之类的)。
展开动画相当简单,因为代理项有一个用于单击处理程序的 MouseArea,它知道自己的位置,因此可以将其传递给启动动画的函数。反过来我想不通:从ListView中的model item/index,如何找出GridView中相关item的坐标?
我在文档中找不到任何似乎可以让您从模型项实例甚至索引访问委托项实例的内容。 GridView 有indexAt(),它根据坐标返回索引。我想我可以反过来做,但它似乎不存在。
这是一个更具体的例子。为篇幅道歉;这是我能想到的准确描述我的问题的最短示例代码:
import QtQuick 1.1
Item {
id: window
width: 400
height: 200
state: "summary"
states: [
State { name: "summary"; },
State { name: "details"; }
]
transitions: [
Transition { from: "summary"; to: "details";
SequentialAnimation {
PropertyAction { target: animationRect; property: "visible"; value: true; }
ParallelAnimation {
NumberAnimation { target: animationRect; properties: "x,y"; to: 0; duration: 200; }
NumberAnimation { target: animationRect; property: "width"; to: 400; duration: 200; }
NumberAnimation { target: animationRect; property: "height"; to: 200; duration: 200; }
}
PropertyAction { target: detailsView; property: "visible"; value: true; }
PropertyAction { target: summaryView; property: "visible"; value: false; }
PropertyAction { target: animationRect; property: "visible"; value: false; }
}
},
Transition { from: "details"; to: "summary";
SequentialAnimation {
PropertyAction { target: summaryView; property: "visible"; value: true; }
// How to animate animationRect back down to the correct item?
PropertyAction { target: detailsView; property: "visible"; value: false; }
}
}
]
Rectangle {
id: animationRect
z: 1
color: "gray"
visible: false
function positionOverSummary(summaryRect) {
x = summaryRect.x; y = summaryRect.y;
width = summaryRect.width; height = summaryRect.height;
}
}
ListModel {
id: data
ListElement { summary: "Item 1"; description: "Lorem ipsum..."; }
ListElement { summary: "Item 2"; description: "Blah blah..."; }
ListElement { summary: "Item 3"; description: "Hurf burf..."; }
}
GridView {
id: summaryView
anchors.fill: parent
cellWidth: 100
cellHeight: 100
model: data
delegate: Rectangle {
color: "lightgray"
width: 95; height: 95;
Text { text: summary; }
MouseArea {
anchors.fill: parent
onClicked: {
var delegateRect = mapToItem(window, x, y);
delegateRect.width = width; delegateRect.height = height;
animationRect.positionOverSummary(delegateRect);
detailsView.positionViewAtIndex(index, ListView.Beginning);
window.state = "details";
}
}
}
}
ListView {
id: detailsView
anchors.fill: parent
visible: false
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: data
delegate: Rectangle {
color: "gray"
width: 400; height: 200;
Column {
Text { text: summary; }
Text { text: description; }
}
MouseArea {
anchors.fill: parent
onClicked: {
// How do I get the coordinates to where animationRect should return?
summaryView.positionViewAtIndex(index, GridView.Visible);
window.state = "summary";
}
}
}
}
}
有什么想法吗?有可能我只是以错误的方式解决这个问题。如果我想要做的具体是不可能的,还有其他方法我应该构建它吗?谢谢!
编辑:我的一些想法(我认为都不可行):
使用
Component.onCompleted和Component.onDestruction保存所有创建的委托项目的列表。为了有用,它应该是模型项或索引 => 委托项的映射。麻烦的是,basic types docs(尤其是variant)似乎表明这种地图不可能在纯 QML 中创建。所以听起来这意味着将这个映射创建为一个 C++ 类,并在 QML 中与委托组件中的onCompleted/onDestruction一起使用它以使其保持最新。对于本应简单的事情,似乎有点危险和笨拙。This mailing list post 似乎表明 Flickable 的
contentItem属性可用于枚举委托项目。然后我发现this post 认为这是不好的做法。我仍在研究它,但我怀疑这将是一个合法的解决方案。看起来太老套了,无法可靠地工作。
到目前为止,这就是我所拥有的。
【问题讨论】: