我目前正在努力将两个看似简单的概念结合起来:交替行颜色和QML ListViews中的平滑移动突出显示项目。
考虑这个简单的例子:
import sys
from PySide6.QtCore import QUrl
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtWidgets import QApplication
if __name__ == '__main__':
app = QApplication([])
engine = QQmlApplicationEngine()
engine.load(QUrl.fromLocalFile('main.qml'))
if not engine.rootObjects():
sys.exit(-1)
app.exec()
import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts
ApplicationWindow {
id: root
width: 400
height: 500
visible: true
font.family: 'Noto Sans'
ListView {
id: listView
width: root.width
height: root.height
clip: true
focus: true
reuseItems: true
boundsBehavior: Flickable.StopAtBounds
model: [
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia",
"Wikipedia is a free online encyclopedia"
]
delegate: Rectangle {
height: 40
width: parent.width
color: ListView.isCurrentItem ? Material.accent : index % 2 === 0 ? palette.base : palette.alternateBase
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
}
}
RowLayout {
height: parent.height
Label {
text: index
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.preferredWidth: 100
}
Label {
text: modelData
Layout.preferredWidth: 300
}
}
}
}
}
这里,我们有一个 ListView 和一个具有交替行颜色的委托。我们可以通过单击或使用箭头键来突出显示该项目:
通过换出几行代码来实现平滑突出显示(无需交替行颜色)也非常简单:
// ...
highlight: Rectangle {
height: 40
width: parent.width
color: Material.accent
}
delegate: Rectangle {
height: 40
width: parent.width
color: 'transparent'
// ...
}
// ...
单独来看,这两个概念都很容易应用,但当它们结合起来时,困难就变得真实了😅
// ...
highlight: Rectangle {
height: 40
width: parent.width
color: Material.accent
}
delegate: Rectangle {
height: 40
width: parent.width
color: ListView.isCurrentItem ? 'transparent' : index % 2 === 0 ? palette.base : palette.alternateBase
// ...
}
// ...
结果
// ...
highlight: Rectangle {
height: 40
width: parent.width
color: Material.accent
z: 1
}
delegate: Rectangle {
height: 40
width: parent.width
color: index % 2 === 0 ? palette.base : palette.alternateBase
// ...
}
// ...
结果
我经常发现自己相信这项任务应该不会太难完成,但我无法摆脱我可能忽略某些事情的感觉。有其他人遇到类似问题并找到解决方案吗?
有趣的问题!
困难是由于物品的z堆叠顺序造成的。 Z 顺序由子树解析,这意味着项目不能将自身堆叠在同级及其子级之间。它要么高于兄弟姐妹及其所有后代,要么低于所有后代。
为了实现您想要的效果,我们需要将背景与委托的内容分开,以便它们不再属于同一子树。 为此,您可以显式设置委托背景(及其几何形状)的父级。我还重构了委托以使用
ItemDelegate
使代码更清晰一点:
highlight: Rectangle {
height: 40
width: parent.width
color: Material.accent
}
delegate: ItemDelegate {
id: delegate
height: 40
width: parent.width
background: Rectangle {
parent: delegate.parent
y: delegate.y
height: delegate.height
color: index % 2 === 0 ? palette.base : palette.alternateBase
}
onClicked: listView.currentIndex = index
contentItem: RowLayout {
Label {
text: index
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.preferredWidth: 100
}
Label {
text: "Wikipedia is a free online encyclopedia"
Layout.preferredWidth: 300
}
}
}
可以通过将
z
设置为 0 表示背景、1 表示突出显示、2 表示代表代表来更明确,但这里似乎可以使用默认顺序。
使用 GammaRay 我们甚至可以看到项目层: