代码之家  ›  专栏  ›  技术社区  ›  Aleph0

用于qml treeview的可重用editordelegate

  •  1
  • Aleph0  · 技术社区  · 6 年前

    我正在努力找出如何创建一个可重用的 EditorDelegate 对于QML TreeView 组件。

    我能够为一个具有该角色的列创建一个可操作的编辑器委托 end . 但是我的 树视图 有3列,即 name , start 结束 .

    我试着简单地设置 styleData.value=textEdit.text 而不是 modelEnd=textEdit.text 但似乎 styleData.value 是只读属性。

    我怎么做我的 编辑代表 所有列都可以重用吗?

    编辑删除.qml 导入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: parent
            }
    
            onAccepted: {
                model.end=textEdit.text; // Can be model.name, model.start, model.<role>???
                textEdit.visible=false
                textDisplay.visible=true
            }
            onFocusChanged: {
                if (!focus) {
                    textEdit.visible=false
                    styleData.value=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()
                }
            }
        }
    }
    

    用法应该是这样的:

    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
        }
    }
    

    我还有一个问题,比如 编辑代表 无法打开和折叠树节点。但这是一个完全不同的故事。

    1 回复  |  直到 6 年前
        1
  •  1
  •   eyllanesc Yonghwan Shin    6 年前

    其思想是,组件清楚地建立了入口和出口,在您的情况下,组件与视图非常相关,因此它很少可重用。更好的设计是只公开一个用模型数据更新的属性,并在其更改时通知它。

    在委托中,我更喜欢在必要时使用加载程序来显示编辑器。

    主CPP

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QStandardItemModel>
    
    #include <QDebug>
    
    enum CustomRoles {
        NameRole = Qt::UserRole + 1000,
        StartRole,
        EndRole
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QStandardItemModel model;
        QObject::connect(&model, &QStandardItemModel::itemChanged, [](QStandardItem *item){
            qDebug()<< item->data(StartRole);
        });
        QHash<int, QByteArray> roles;
        roles[NameRole] = "name";
        roles[StartRole] = "start";
        roles[EndRole] = "end";
        model.setItemRoleNames(roles);
    
        for(int i=0; i<4; ++i){
            QStandardItem *parent_item = new QStandardItem();
            model.invisibleRootItem()->appendRow(parent_item);
            parent_item->setData(QString("name-%1").arg(i), NameRole);
            parent_item->setData(QString("start-%1").arg(i), StartRole);
            parent_item->setData(QString("end-%1").arg(i), EndRole);
            for (int j=0; j<5; ++j) {
                QStandardItem *child_item = new QStandardItem();
                parent_item->appendRow(child_item);
                child_item->setData(QString("name-%1-%2").arg(i).arg(j), NameRole);
                child_item->setData(QString("start-%1-%2").arg(i).arg(j), StartRole);
                child_item->setData(QString("end-%1-%2").arg(i).arg(j), EndRole);
            }
        }
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("itemModel", &model);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    MQ.QML

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
        TreeView {
            id: treeView
            anchors.fill: parent
            TableViewColumn {
                title: "Value"
                role: "name"
                delegate: EditorDelegate{
                    text: styleData.value
                    onTextChanged: model.name = text
                }
            }
            TableViewColumn {
                title: "Start"
                id: start
                role: "start"
                delegate: EditorDelegate{
                    text: styleData.value
                    onTextChanged: model.start = text
                }
            }
            TableViewColumn {
                title: "End"
                id: end
                role: "end"
                delegate: EditorDelegate{
                    text: styleData.value
                    onTextChanged: model.end = text
                }
            }
            model: itemModel
        }
    }
    

    编辑删除.qml

    import QtQuick 2.0
    
    Rectangle {
        id: root
        property string text
        property bool mode: false
        Component{
            id: component_display
            Text{}
        }
        Component{
            id: component_edit
            TextInput{}
        }
        Loader{
            id: loader
            anchors.fill: parent
            sourceComponent: mode ? component_edit: component_display
            onSourceComponentChanged: {
                loader.item.text = root.text
                if(sourceComponent === component_edit){
                    loader.item.editingFinished.connect(onEditingFinished)
                    loader.item.forceActiveFocus()
                }
            }
            function onEditingFinished(){
                text = loader.item.text
                mode = false
            }
            MouseArea{
                anchors.fill: parent
                onDoubleClicked: {
                    if (mouse.button & Qt.LeftButton)
                        mode = true
                }
            }
        }
    }