您提出了不同的问题,这次我将回答所有问题,但下次您将必须按照 SO 指南中的指示为每个问题创建一个帖子。
在您的情况下,需要 3 个元素:
将图像加载到 GridView 中:建议实现一个模型,在本例中,基于具有自定义角色的 QStandardItemModel 实现它,并与委托建立连接。
Filter:为此,您可以使用 DelegateModel 或 QSortFilterProxyModel,在本例中使用第二个选项,因为它按角色并通过正则表达式实现过滤。
悬停动画:首先是检测鼠标何时进入或退出项目,为此使用 MouseArea 来触发进入和退出信号。然后我们使用Behavior来设置“y”属性改变时的动画。然后只需要在信号被触发时设置各自的最终值即可。我已删除“anchors.bottom:parent.bottom”,因为锚点不允许修改属性。
另一方面,如果您为委托创建 qml,则无需使用 Component,因为它本身就是一个组件,另一方面,您必须启用“clip”属性,以便项目的绘制不会超出其范围。自己的区域。
综合以上情况,解决方案是:
├── images
│ └── android.png
├── main.py
└── qml
├── main.qml
└── ThumbDelegate.qml
main.py
import os
import sys
from PySide2 import QtCore, QtGui, QtWidgets, QtQml
class CustomModel(QtGui.QStandardItemModel):
TitleRole = QtCore.Qt.UserRole + 1000
UrlRole = QtCore.Qt.UserRole + 1001
def __init__(self, parent=None):
super().__init__(parent)
self.setItemRoleNames(
{CustomModel.TitleRole: b"title", CustomModel.UrlRole: b"thumbnail"}
)
@QtCore.Slot(str, QtCore.QUrl)
def addItem(self, title, url):
it = QtGui.QStandardItem()
it.setData(title, CustomModel.TitleRole)
it.setData(url, CustomModel.UrlRole)
self.appendRow(it)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
current_dir = os.path.dirname(os.path.realpath(__file__))
model = CustomModel()
# add items
for (
text
) in "amputate arena accept architecture astonishing advertise abortion apple absolute advice".split():
title = text
image_path = os.path.join(current_dir, "images", "android.png")
model.addItem(title, QtCore.QUrl.fromLocalFile(image_path))
proxy_filter = QtCore.QSortFilterProxyModel()
proxy_filter.setSourceModel(model)
proxy_filter.setFilterRole(CustomModel.TitleRole)
engine = QtQml.QQmlApplicationEngine()
engine.rootContext().setContextProperty("proxy_filter", proxy_filter)
filename = os.path.join(current_dir, "qml", "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(filename))
if not engine.rootObjects():
sys.exit(-1)
engine.quit.connect(app.quit)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
ApplicationWindow {
id: mainWindowId
visible: true
width: 1280
height: 720
title: qsTr("Image Hover Effect")
Rectangle {
anchors.fill: parent
ColumnLayout {
anchors.fill: parent
spacing: 0
TextField{
id: filterTextFieldId
Layout.fillWidth: true
Layout.preferredHeight: 40
font {
family: "SF Pro Display"
pixelSize: 22
}
color: "dodgerblue"
onTextChanged: proxy_filter.setFilterRegExp(text)
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "gold"
GridView {
clip: true
id: thumbViewId
anchors.fill: parent
anchors.margins: 25
cellWidth: 260
cellHeight: 260
model: proxy_filter
delegate: ThumbDelegate {
source: model.thumbnail
title: model.title
}
focus: true
}
}
}
}
}
ThumbDelegate.qml
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
Rectangle {
id: root
width: 256
height: 256
color: 'green'
clip: true
property alias source: thumbImageId.source
property alias title: label.text
Image {
id: thumbImageId
asynchronous: true
anchors.fill: parent
}
Rectangle {
id: base
width: parent.width
height: 50
color: 'grey'
y: root.height
Behavior on y { NumberAnimation {duration: 500} }
Label {
id: label
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
font.family: 'SF Pro Display'
font.pointSize: 22
color: 'white'
}
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
onEntered: base.y = root.height - base.height
onExited: base.y = root.height
}
}
Update:
看到你已经更新了你的问题,只需要修改python代码,qml代码必须与我在上一部分答案中提出的相同。
*.py
import os
import sys
from PySide2 import QtCore, QtGui, QtWidgets, QtQml
class InventoryModel(QtCore.QAbstractListModel):
TitleRole = QtCore.Qt.UserRole + 1000
ThumbnailRole = QtCore.Qt.UserRole + 1001
def __init__(self, entries, parent=None):
super().__init__(parent)
self._entries = entries
def rowCount(self, parent=QtCore.QModelIndex()):
return 0 if parent.isValid() else len(self._entries)
def data(self, index, role=QtCore.Qt.DisplayRole):
if 0 <= index.row() < self.rowCount() and index.isValid():
item = self._entries[index.row()]
if role == InventoryModel.TitleRole:
return item["title"]
elif role == InventoryModel.ThumbnailRole:
return item["thumbnail"]
def roleNames(self):
roles = dict()
roles[InventoryModel.TitleRole] = b"title"
roles[InventoryModel.ThumbnailRole] = b"thumbnail"
return roles
def appendRow(self, n, t):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self._entries.append(dict(title=n, thumbnail=t))
self.endInsertRows()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
current_dir = os.path.dirname(os.path.realpath(__file__))
entries = [
{"title": "Zero", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/zero.png"},
{"title": "One", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/one.png"},
{"title": "Two", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/two.png"},
{"title": "Three", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/three.png"},
{"title": "Four", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/four.png"},
{"title": "Five", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/five.png"},
{"title": "Six", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/six.png"},
{"title": "Seven", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/seven.png"},
{"title": "Eight", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/eight.png"},
{"title": "Nine", "thumbnail": "file:///E:/Tech/QML/projects/Test_005/nine.png"},
]
assetModel = InventoryModel(entries)
engine = QtQml.QQmlApplicationEngine()
proxy_filter = QtCore.QSortFilterProxyModel()
proxy_filter.setSourceModel(assetModel)
proxy_filter.setFilterRole(InventoryModel.TitleRole)
engine.rootContext().setContextProperty("proxy_filter", proxy_filter)
engine.load(QtCore.QUrl.fromLocalFile('E:/Tech/QML/projects/Test_005/main.qml'))
if not engine.rootObjects():
sys.exit(-1)
engine.quit.connect(app.quit)
sys.exit(app.exec_())