将 ListView currentItem 信息传递给外部组件
Pass ListView currentItem info to external component
我正在使用 Qt 逻辑作为 backbone 应用程序开发 QML,我遇到以下情况:
在启动时,QML ApplicationWindow
与其 StatusBar
一起显示,其中包含两个状态图标和一个可检查的 Button
,名为 UeStaffSelector
用于工作人员登录。当我按下 UeStaffSelector
时,Window
named ueStaffView
(它包含 ListView
named ueListViewWorkers
)弹出并从 ueListViewWorkers
用户选择登录过程, 如下截图所示:
现在,我有另一个自定义 QML Item
,名为 UeKeypad
,代表用户的 pin 输入,因此 he/she 可以成功登录系统。从ListView
中选择delegate
后,必须弹出此UeKeypad
。
问题是,我从哪里调用 UeKeypad
?从 delegate
、ListView
还是 ApplicationWindow
?另外,如何将用户信息(用户图像、用户名和用户密码)传递给 UeKeypad
?
QML 绑定很酷,非常酷。您可以声明键盘类型与当前委托内的类型之间的直接连接,即当前 Image
和 user/password,而不是强制传递数据。这样,一旦选择了代表,就会设置键盘内的相应变量。
这个结果可以使用 State
s 来实现。我们定义了两个 State
s,一个 VISIBLE
状态用于向用户显示 image/username 的键盘和一个 HIDDEN
状态用于隐藏键盘,当没有选择可用时。明智地使用 when
子句,即以互斥的方式,我们可以确保永远不会命中默认值 - 空字符串 - State
,因此组件的整体 state
总是持续的。
使用 State
s 的一个副作用是我们可以很容易地定义一个 Transition
在两个 State
s 之间移动,从而定义你感兴趣的那种滑动效果中。另外,通过以声明的方式定义所有关联,表单仍然可以与设计者edited/viewed。使用命令式代码这是不可能的。
可以通过以下方式访问当前委托中的实际值
currentItem
中的值(如果在顶级类型中不可用,则 alias
ed)或通过模型 get
。注意 index
的用法,Repeater
和 ListView
的附加 属性。
以下示例总结了这种方法,还提供了两种访问 ListView
数据的方法。
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
ApplicationWindow {
width: 600
height: 800
visible: true
Column {
id: keypad
x: parent.width - width // put in the corner
z: 2
Row {
width: 200
spacing: 10
Image {
id: keyImage
width: 100
height: 100
}
Text {
id: keyText
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 30
}
}
Grid{
columns: 3
columnSpacing: 5
rowSpacing: 5
Repeater {
model: 9
Button {
text: index + 1
onClicked: console.info(text + " " + keyText.text)
}
}
}
states: [
State {
name: "HIDDEN"
PropertyChanges {
target: keypad
y: keypad.parent.height
}
when: list.currentIndex < 0
},
State {
name: "VISIBLE"
PropertyChanges {
target: keypad
y: keypad.parent.height / 2 - keypad.height / 2
}
PropertyChanges {
target: keyImage
source: list.model.get(list.currentIndex).image//list.currentItem.imagePath
}
PropertyChanges {
target: keyText
text: list.model.get(list.currentIndex).user//list.currentItem.label
}
when: list.currentIndex >= 0
}
]
transitions: Transition {
NumberAnimation {
properties: "y";
duration: 1000
easing.type: Easing.InQuad
}
}
}
ListView {
id: list
anchors.fill: parent
currentIndex: -1
model: ListModel{
ListElement {
image: "http://www.theapricity.com/forum/image.php?u=9098&dateline=1442619767"
user: "first"
}
ListElement {
image: "http://a.dilcdn.com/bl/wp-content/uploads/sites/8/2013/10/angry-cat-200x200.jpg"
user: "second"
}
ListElement {
image: "http://images.all-free-download.com/images/graphicthumb/walking_sand_cat_516744.jpg"
user: "third"
}
}
delegate: Rectangle {
width: ListView.view.width
height: 220
property alias imagePath: img.source
property alias label: label.text
RowLayout {
anchors.fill: parent
Image {
id: img
width: 100
height: 100
fillMode: Image.PreserveAspectFit
source: image
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: 100
}
Text {
id: label
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
text: user
font.pixelSize: 30
}
MouseArea{
anchors.fill: parent
onClicked: list.currentIndex = index //set the current item
}
}
color: ListView.isCurrentItem ? "steelblue" : "transparent"
scale: ListView.isCurrentItem ? 1 : 0.7
}
}
}
正如我们上面所讨论的,与命令式方法相比,这种方法显然具有许多优势。主要是因为 更自然 在 QML 中定义(某种)执行工作流的方式。您仍然可以(有时更容易)为此目的定义命令式代码。请注意,在大多数情况下,如果您遵循命令式方式,那么您只是 "doing it wrong".
我正在使用 Qt 逻辑作为 backbone 应用程序开发 QML,我遇到以下情况:
在启动时,QML ApplicationWindow
与其 StatusBar
一起显示,其中包含两个状态图标和一个可检查的 Button
,名为 UeStaffSelector
用于工作人员登录。当我按下 UeStaffSelector
时,Window
named ueStaffView
(它包含 ListView
named ueListViewWorkers
)弹出并从 ueListViewWorkers
用户选择登录过程, 如下截图所示:
现在,我有另一个自定义 QML Item
,名为 UeKeypad
,代表用户的 pin 输入,因此 he/she 可以成功登录系统。从ListView
中选择delegate
后,必须弹出此UeKeypad
。
问题是,我从哪里调用 UeKeypad
?从 delegate
、ListView
还是 ApplicationWindow
?另外,如何将用户信息(用户图像、用户名和用户密码)传递给 UeKeypad
?
QML 绑定很酷,非常酷。您可以声明键盘类型与当前委托内的类型之间的直接连接,即当前 Image
和 user/password,而不是强制传递数据。这样,一旦选择了代表,就会设置键盘内的相应变量。
这个结果可以使用 State
s 来实现。我们定义了两个 State
s,一个 VISIBLE
状态用于向用户显示 image/username 的键盘和一个 HIDDEN
状态用于隐藏键盘,当没有选择可用时。明智地使用 when
子句,即以互斥的方式,我们可以确保永远不会命中默认值 - 空字符串 - State
,因此组件的整体 state
总是持续的。
使用 State
s 的一个副作用是我们可以很容易地定义一个 Transition
在两个 State
s 之间移动,从而定义你感兴趣的那种滑动效果中。另外,通过以声明的方式定义所有关联,表单仍然可以与设计者edited/viewed。使用命令式代码这是不可能的。
可以通过以下方式访问当前委托中的实际值
currentItem
中的值(如果在顶级类型中不可用,则 alias
ed)或通过模型 get
。注意 index
的用法,Repeater
和 ListView
的附加 属性。
以下示例总结了这种方法,还提供了两种访问 ListView
数据的方法。
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
ApplicationWindow {
width: 600
height: 800
visible: true
Column {
id: keypad
x: parent.width - width // put in the corner
z: 2
Row {
width: 200
spacing: 10
Image {
id: keyImage
width: 100
height: 100
}
Text {
id: keyText
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 30
}
}
Grid{
columns: 3
columnSpacing: 5
rowSpacing: 5
Repeater {
model: 9
Button {
text: index + 1
onClicked: console.info(text + " " + keyText.text)
}
}
}
states: [
State {
name: "HIDDEN"
PropertyChanges {
target: keypad
y: keypad.parent.height
}
when: list.currentIndex < 0
},
State {
name: "VISIBLE"
PropertyChanges {
target: keypad
y: keypad.parent.height / 2 - keypad.height / 2
}
PropertyChanges {
target: keyImage
source: list.model.get(list.currentIndex).image//list.currentItem.imagePath
}
PropertyChanges {
target: keyText
text: list.model.get(list.currentIndex).user//list.currentItem.label
}
when: list.currentIndex >= 0
}
]
transitions: Transition {
NumberAnimation {
properties: "y";
duration: 1000
easing.type: Easing.InQuad
}
}
}
ListView {
id: list
anchors.fill: parent
currentIndex: -1
model: ListModel{
ListElement {
image: "http://www.theapricity.com/forum/image.php?u=9098&dateline=1442619767"
user: "first"
}
ListElement {
image: "http://a.dilcdn.com/bl/wp-content/uploads/sites/8/2013/10/angry-cat-200x200.jpg"
user: "second"
}
ListElement {
image: "http://images.all-free-download.com/images/graphicthumb/walking_sand_cat_516744.jpg"
user: "third"
}
}
delegate: Rectangle {
width: ListView.view.width
height: 220
property alias imagePath: img.source
property alias label: label.text
RowLayout {
anchors.fill: parent
Image {
id: img
width: 100
height: 100
fillMode: Image.PreserveAspectFit
source: image
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: 100
}
Text {
id: label
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
text: user
font.pixelSize: 30
}
MouseArea{
anchors.fill: parent
onClicked: list.currentIndex = index //set the current item
}
}
color: ListView.isCurrentItem ? "steelblue" : "transparent"
scale: ListView.isCurrentItem ? 1 : 0.7
}
}
}
正如我们上面所讨论的,与命令式方法相比,这种方法显然具有许多优势。主要是因为 更自然 在 QML 中定义(某种)执行工作流的方式。您仍然可以(有时更容易)为此目的定义命令式代码。请注意,在大多数情况下,如果您遵循命令式方式,那么您只是 "doing it wrong".