尝试以编程方式在 ListView 中居中项目
Trying to center items programmatically in a ListView
我希望在 QML ListView
中居中项目,因此我添加了以下 ListView
代码:
import QtQuick 2.0
import QtMultimedia 5.5
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QtTest 1.1
Rectangle {
id: ueKeypad
width: ueMainColumnLayout.implicitWidth+2*radius
height: ueMainColumnLayout.implicitHeight+2*radius
color: "grey"
radius: 8
border.color: "#99c6f0"
border.width: 4
ColumnLayout {
id: ueMainColumnLayout
anchors.fill: parent
anchors.margins: radius
spacing: 4
RowLayout {
id: ueTextLayout
Text {
id: ueStaffLoginText
text: qsTr("Staff Login")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.family: "Padauk"
textFormat: Text.RichText
font.pointSize: 16
font.bold: true
color: ueKeypad.border.color
Layout.fillWidth: true
} // ueStaffLoginText
} // ueTextLayout
RowLayout {
id: uePeopleViewLayout
ListView {
id: uePeopleView
keyNavigationWraps: true
spacing: 4
antialiasing: true
model: uePeopleModel
Layout.fillWidth: true
Layout.fillHeight: false
//Layout.minimumWidth: 64
Layout.minimumHeight: 64
//Layout.preferredWidth: 96
Layout.preferredHeight: 96
//Layout.maximumWidth: 128
Layout.maximumHeight: 128
orientation: ListView.Horizontal
layoutDirection: Qt.LeftToRight
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.ApplyRange
Component.onCompleted: {
var newIndex=(count%2==0)?(count/2):(Math.round(count/2));
positionViewAtIndex(newIndex, ListView.Center);
currentIndex=newIndex;
print(newIndex)
} // onCompleted - center items
delegate: Rectangle {
id: uePersonDelegate
width: 32
height: 32
ColumnLayout {
id: uePersonDelegateMainLayout
anchors.fill: parent
anchors.margins: radius
RowLayout {
id: uePersonDelegateImageLayout
Image {
id: uePersonImage
antialiasing: true
fillMode: Image.PreserveAspectFit
source: "image://uePeopleModel/"+model.ueRoleImage
} // uePersonImage
} // uePersonDelegateImageLayout
RowLayout {
id: uePersonDelegateNameLayout
Text {
id: ueTextPersonName
color: "#ffffff"
text: model.ueRoleName
font.bold: true
font.pixelSize: 16
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // ueTextPersonName
} // uePersonDelegateNameLayout
} // uePersonDelegateMainLayout
} // uePersonDelegate
add: Transition {
NumberAnimation {
property: "opacity";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
NumberAnimation {
property: "scale";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
} // Transition
displaced: Transition {
NumberAnimation {
properties: "x,y";
duration: 100;
easing.type: Easing.OutBounce
} // NumberAnimation
} // Transition
} // uePeopleView
} // uePeopleViewLayout
RowLayout {
id: ueTumblerLayout
Tumbler {
id: ueLoginKeypadTumbler
Layout.fillWidth: true
Layout.fillHeight: false
height: 100
antialiasing: true
TumblerColumn {
id: ueNumericTumblerColumnDigit1000
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1000
TumblerColumn {
id: ueNumericTumblerColumnDigit100
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit100
TumblerColumn {
id: ueNumericTumblerColumnDigit10
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit10
TumblerColumn {
id: ueNumericTumblerColumnDigit1
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1
} // ueLoginKeypadTumbler
} // ueTumblerLayout
RowLayout {
id: ueButtonsLayout
Button {
id: ueButtonLogin
Layout.fillWidth: true
text: qsTr("Login")
} // ueButtonLogin
Button {
id: ueButtonClear
Layout.fillWidth: true
text: qsTr("Clear")
} // ueButtonClear
Button {
id: ueButtonQuitApp
Layout.fillWidth: true
text: qsTr("Quit")
} // ueButtonQuitApp
} // ueButtonsLayout
} // ueMainColumnLayout
states: [
State {
name: "ueStateLoginOk"
PropertyChanges {
target: ueKeypad
border.color: "#00ff00"
}
PropertyChanges {
target: ueLoginText
color: "#00ff00"
}
}, // ueStateLoginOk
State {
name: "ueStateLoginOkFailed"
PropertyChanges {
target: ueKeypad
border.color: "#ff0000"
}
PropertyChanges {
target: ueLoginText
color: "#ff0000"
}
} // ueStateLoginOkFailed
] // states
} // ueKeypad
现在,print(newIndex)
语句打印出正确的值 3
(在我的例子中,因为目前我有 5 个项目),我希望第 3 个项目位于ListView
等左右两栏。这可能吗?在这个问题的范围之外,为什么 Transition
s 也不起作用,例如?
我还根据评论提示设置了 highlightRangeMode: ListView.ApplyRange
。
问题截图如下:
这里的问题是您试图根据需要安排 ListView
代表。这是完全错误的,因为根据 ListView
大小 ,ListView
(与所有其他视图非常相似)旨在为您做到这一点。 ListView
将 始终 使用 所有 可用的 space,导致委托全部位于左侧,因为您经验丰富。
您应该限制 ListView
大小并将其放置在中心,而不是将行为强加给代表。然后,您可以利用 highlightRangeMode
与 preferredHighlightBegin
和 的 preferredHighlightEnd
来确保当前 selected Item
位于列表的中心.此外,通过使用 StrictlyEnforceRange
,您可以强制 selected Item
保持 always 在中心,这将导致 IMO 更好的方法select 所需的 Item
.
下面是一个实施此方法的示例。为简单起见,尺寸是硬编码的,但可以很容易地进行参数化。如前所述,我通过设置突出显示策略走得更远。希望对你有帮助。
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
Window {
id: win
width: 300
height: 300
visible: true
ColumnLayout {
anchors.fill: parent
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "blue"
}
ListView {
Layout.alignment: Qt.AlignCenter
Layout.minimumWidth: 30 * 5 + 40
Layout.preferredHeight: 50
clip: true
spacing: 15
model: 10
orientation: ListView.Horizontal
delegate: Item {
width: 30
height: 50
Rectangle{
anchors.centerIn: parent
color: parent.ListView.isCurrentItem ? "red" : "steelblue"
width: 30
height: 30
Text {
text: index
anchors.centerIn: parent
}
scale: parent.ListView.isCurrentItem ? 1.5 : 1
Behavior on scale { NumberAnimation { duration: 200 } }
}
}
preferredHighlightBegin: width / 2 - 15
preferredHighlightEnd: width / 2 + 15
highlightRangeMode: ListView.StrictlyEnforceRange
Component.onCompleted: currentIndex = count / 2
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "yellow"
}
}
}
我希望在 QML ListView
中居中项目,因此我添加了以下 ListView
代码:
import QtQuick 2.0
import QtMultimedia 5.5
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QtTest 1.1
Rectangle {
id: ueKeypad
width: ueMainColumnLayout.implicitWidth+2*radius
height: ueMainColumnLayout.implicitHeight+2*radius
color: "grey"
radius: 8
border.color: "#99c6f0"
border.width: 4
ColumnLayout {
id: ueMainColumnLayout
anchors.fill: parent
anchors.margins: radius
spacing: 4
RowLayout {
id: ueTextLayout
Text {
id: ueStaffLoginText
text: qsTr("Staff Login")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.family: "Padauk"
textFormat: Text.RichText
font.pointSize: 16
font.bold: true
color: ueKeypad.border.color
Layout.fillWidth: true
} // ueStaffLoginText
} // ueTextLayout
RowLayout {
id: uePeopleViewLayout
ListView {
id: uePeopleView
keyNavigationWraps: true
spacing: 4
antialiasing: true
model: uePeopleModel
Layout.fillWidth: true
Layout.fillHeight: false
//Layout.minimumWidth: 64
Layout.minimumHeight: 64
//Layout.preferredWidth: 96
Layout.preferredHeight: 96
//Layout.maximumWidth: 128
Layout.maximumHeight: 128
orientation: ListView.Horizontal
layoutDirection: Qt.LeftToRight
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.ApplyRange
Component.onCompleted: {
var newIndex=(count%2==0)?(count/2):(Math.round(count/2));
positionViewAtIndex(newIndex, ListView.Center);
currentIndex=newIndex;
print(newIndex)
} // onCompleted - center items
delegate: Rectangle {
id: uePersonDelegate
width: 32
height: 32
ColumnLayout {
id: uePersonDelegateMainLayout
anchors.fill: parent
anchors.margins: radius
RowLayout {
id: uePersonDelegateImageLayout
Image {
id: uePersonImage
antialiasing: true
fillMode: Image.PreserveAspectFit
source: "image://uePeopleModel/"+model.ueRoleImage
} // uePersonImage
} // uePersonDelegateImageLayout
RowLayout {
id: uePersonDelegateNameLayout
Text {
id: ueTextPersonName
color: "#ffffff"
text: model.ueRoleName
font.bold: true
font.pixelSize: 16
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // ueTextPersonName
} // uePersonDelegateNameLayout
} // uePersonDelegateMainLayout
} // uePersonDelegate
add: Transition {
NumberAnimation {
property: "opacity";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
NumberAnimation {
property: "scale";
from: 0;
to: 1.0;
duration: 100
} // NumberAnimation
} // Transition
displaced: Transition {
NumberAnimation {
properties: "x,y";
duration: 100;
easing.type: Easing.OutBounce
} // NumberAnimation
} // Transition
} // uePeopleView
} // uePeopleViewLayout
RowLayout {
id: ueTumblerLayout
Tumbler {
id: ueLoginKeypadTumbler
Layout.fillWidth: true
Layout.fillHeight: false
height: 100
antialiasing: true
TumblerColumn {
id: ueNumericTumblerColumnDigit1000
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1000
TumblerColumn {
id: ueNumericTumblerColumnDigit100
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit100
TumblerColumn {
id: ueNumericTumblerColumnDigit10
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit10
TumblerColumn {
id: ueNumericTumblerColumnDigit1
model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
} // ueNumericTumblerColumnDigit1
} // ueLoginKeypadTumbler
} // ueTumblerLayout
RowLayout {
id: ueButtonsLayout
Button {
id: ueButtonLogin
Layout.fillWidth: true
text: qsTr("Login")
} // ueButtonLogin
Button {
id: ueButtonClear
Layout.fillWidth: true
text: qsTr("Clear")
} // ueButtonClear
Button {
id: ueButtonQuitApp
Layout.fillWidth: true
text: qsTr("Quit")
} // ueButtonQuitApp
} // ueButtonsLayout
} // ueMainColumnLayout
states: [
State {
name: "ueStateLoginOk"
PropertyChanges {
target: ueKeypad
border.color: "#00ff00"
}
PropertyChanges {
target: ueLoginText
color: "#00ff00"
}
}, // ueStateLoginOk
State {
name: "ueStateLoginOkFailed"
PropertyChanges {
target: ueKeypad
border.color: "#ff0000"
}
PropertyChanges {
target: ueLoginText
color: "#ff0000"
}
} // ueStateLoginOkFailed
] // states
} // ueKeypad
现在,print(newIndex)
语句打印出正确的值 3
(在我的例子中,因为目前我有 5 个项目),我希望第 3 个项目位于ListView
等左右两栏。这可能吗?在这个问题的范围之外,为什么 Transition
s 也不起作用,例如?
我还根据评论提示设置了 highlightRangeMode: ListView.ApplyRange
。
问题截图如下:
这里的问题是您试图根据需要安排 ListView
代表。这是完全错误的,因为根据 ListView
大小 ,ListView
(与所有其他视图非常相似)旨在为您做到这一点。 ListView
将 始终 使用 所有 可用的 space,导致委托全部位于左侧,因为您经验丰富。
您应该限制 ListView
大小并将其放置在中心,而不是将行为强加给代表。然后,您可以利用 highlightRangeMode
与 preferredHighlightBegin
和 preferredHighlightEnd
来确保当前 selected Item
位于列表的中心.此外,通过使用 StrictlyEnforceRange
,您可以强制 selected Item
保持 always 在中心,这将导致 IMO 更好的方法select 所需的 Item
.
下面是一个实施此方法的示例。为简单起见,尺寸是硬编码的,但可以很容易地进行参数化。如前所述,我通过设置突出显示策略走得更远。希望对你有帮助。
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
Window {
id: win
width: 300
height: 300
visible: true
ColumnLayout {
anchors.fill: parent
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "blue"
}
ListView {
Layout.alignment: Qt.AlignCenter
Layout.minimumWidth: 30 * 5 + 40
Layout.preferredHeight: 50
clip: true
spacing: 15
model: 10
orientation: ListView.Horizontal
delegate: Item {
width: 30
height: 50
Rectangle{
anchors.centerIn: parent
color: parent.ListView.isCurrentItem ? "red" : "steelblue"
width: 30
height: 30
Text {
text: index
anchors.centerIn: parent
}
scale: parent.ListView.isCurrentItem ? 1.5 : 1
Behavior on scale { NumberAnimation { duration: 200 } }
}
}
preferredHighlightBegin: width / 2 - 15
preferredHighlightEnd: width / 2 + 15
highlightRangeMode: ListView.StrictlyEnforceRange
Component.onCompleted: currentIndex = count / 2
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "yellow"
}
}
}