如何为QML TreeView创建可复用的EditorDelegate
解决QML TreeView EditorDelegate适配多列的问题
我来帮你搞定这个多列适配的问题!核心思路是利用styleData.role来动态获取当前列对应的字段名,这样就不用硬编码model.end这类固定属性了,同时要注意styleData.value确实是只读的,不能直接赋值,我们需要通过修改model的对应属性来实现数据更新。
关键修改点
- 用
styleData.role动态获取当前列的role名称(比如"name"、"start"、"end"),然后通过model[styleData.role]来访问和修改对应的数据 - 移除
styleData.value = textEdit.text这行错误代码,因为styleData.value是只读的,model更新后textDisplay的text会自动同步(因为它绑定了styleData.value)
修改后的EditorDelegate.qml
import QtQuick 2.0 Rectangle { anchors.fill: parent Text { anchors.fill: parent id: textDisplay visible: true text: styleData.value } TextInput { anchors.fill: parent id: textEdit text: styleData.value visible: false onVisibleChanged: { focus = true; // 直接设置焦点为true即可 } onAccepted: { // 动态根据当前列的role修改model对应属性 model[styleData.role] = textEdit.text; textEdit.visible = false; textDisplay.visible = true; } onFocusChanged: { if (!focus) { textEdit.visible = false; // 失去焦点时同步修改model model[styleData.role] = textEdit.text; textDisplay.visible = true; } } } MouseArea { id: mouseArea acceptedButtons: Qt.AllButtons anchors.fill: parent onDoubleClicked: { if (mouse.button & Qt.LeftButton) { textDisplay.visible = false; textEdit.visible = true; textEdit.forceActiveFocus(); } } } }
验证你的预期使用方式
你的TreeView代码完全可以直接使用修改后的Delegate,因为每个TableViewColumn的role会被styleData.role自动捕获:
import QtQuick 2.9 import QtQuick.Window 2.3 import QtQuick.Controls 1.4 Window { visible: true TreeView { id: treeView anchors.fill: parent TableViewColumn { title: "Value" role: "name" delegate: EditorDelegate { } } TableViewColumn { title: "Start" id: start role: "start" delegate: EditorDelegate { } } TableViewColumn { title: "End" id: end role: "end" delegate: EditorDelegate { } } model: itemModel // 确保你的model是可编辑的,比如QStandardItemModel或自定义可编辑Model } }
额外注意事项
- 确保你的
itemModel是支持编辑的,比如使用QStandardItemModel时要设置ItemIsEditable标志,或者自定义Model实现setData方法 - 关于树节点展开折叠的问题,你可以通过在Delegate中添加对
styleData.hasChildren和styleData.expanded的处理,比如添加一个小箭头图标来控制展开/折叠,这确实是独立的功能,需要的话可以再单独实现
内容的提问来源于stack exchange,提问作者Aleph0
相关产品推荐
相关产品推荐

