Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过带有自定义委托的TableView编辑QStandardItemModel_C++_Qt_Qml_Qt5_Qstandarditemmodel - Fatal编程技术网

C++ 通过带有自定义委托的TableView编辑QStandardItemModel

C++ 通过带有自定义委托的TableView编辑QStandardItemModel,c++,qt,qml,qt5,qstandarditemmodel,C++,Qt,Qml,Qt5,Qstandarditemmodel,我有一个QStandarItemModel,通过QML表格视图显示 模型如下: class mystandardmodel: public QStandardItemModel { public: mystandardmodel(); enum Role { role1=Qt::UserRole, role2 }; explicit mystandardmodel(QObject * parent = 0): QStan

我有一个QStandarItemModel,通过QML表格视图显示

模型如下:

class mystandardmodel: public QStandardItemModel
{

public:
    mystandardmodel();
    enum Role {
         role1=Qt::UserRole,
         role2
     };

     explicit mystandardmodel(QObject * parent = 0): QStandardItemModel(parent){}
     //explicit mystandardmodel( int rows, int columns, QObject * parent = 0 )
     //    : QStandardItemModel(rows, columns, parent){}

     QHash<int, QByteArray> roleNames() const{
          QHash<int, QByteArray> roles;
          roles[role1] = "one";
          roles[role2] = "two";
          return roles;
 }
};
我这样填充模型:

 mystandardmodel* mysmodel=new mystandardmodel(0);
 QStandardItem* it = new QStandardItem();
 it->setData("data1", mystandardmodel::role1);
 it->setData(true, mystandardmodel::role2);
 it->setCheckable(true);
 it->setEditable(true);
 mysmodel->appendRow(it);
 QStandardItem* it2 = new QStandardItem();
 it2->setData("data2",mystandardmodel::role1);
 it2->setData("teststring",mystandardmodel::role2);
 mysmodel->appendRow(it2);
如何使模型处于可编辑状态,以便使用复选框或编辑文本被传输回模型

编辑:我尝试按照中的建议使用集合模型:

Component {
    id: myDelegate
    Loader {
        property var roleTwo: model.two
        property int thisIndex: model.index
        sourceComponent: if(typeof(roleTwo)=='boolean') {
                             checkBoxDelegate}
                         else { stringDelegate}
    }
}

Component {
    id: checkBoxDelegate
    CheckBox{text: roleTwo
        onCheckedChanged: {
            myTestModel.setData(0,"two",false)
            console.log('called',thisIndex)
        }
    }

}

Component {
    id: stringDelegate
    TextEdit {text: roleTwo
        onEditingFinished: {
            myTestModel.setData(thisIndex,"two",text)
           console.log('called',thisIndex)
        }
    }
}
索引还可以,但似乎没有效果(我添加了具有相同模型的第二个TableView,但是如果我在第一个TableView中编辑它,那里的数据不会更新)

使用
setData()
可能是一个选项,但它需要一个整数值来指示QML中无法访问的角色,或者更确切地说是不优雅

更好的选择是创建一个新的
Q\u可调用的
。由于更新是在视图中给出的,因此除了引起奇怪的事件外,不需要通知它

为了获得行,我们使用几何体和
TableView
rowAt()方法

以下是一个例子:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QStandardItemModel>

class MyStandardModel: public QStandardItemModel
{
    Q_OBJECT
public:
    enum Role {
        role1=Qt::UserRole+1,
        role2
    };

    using QStandardItemModel::QStandardItemModel;

    QHash<int, QByteArray> roleNames() const{
        QHash<int, QByteArray> roles;
        roles[role1] = "one";
        roles[role2] = "two";
        return roles;
    }

    Q_INVOKABLE void updateValue(int row, QVariant value, const QString &roleName){

        int role = roleNames().key(roleName.toUtf8());
        QStandardItem *it = item(row);
        if(it){
            blockSignals(true);
            it->setData(value, role);
            Q_ASSERT(it->data(role)==value);
            blockSignals(false);
        }

    }
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    MyStandardModel model;

    for(int i=0; i< 10; i++){
        auto item = new QStandardItem;
        item->setData(QString("data1 %1").arg(i), MyStandardModel::role1);
        if(i%2 == 0)
            item->setData(true, MyStandardModel::role2);
        else {
            item->setData(QString("data2 %1").arg(i), MyStandardModel::role2);
        }
        model.appendRow(item);
    }
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("myTestModel", &model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

#include "main.moc"

完整的示例可以在下面找到。

您可以直接将值设置为
model.two
,该值将自动调用
setData
,并具有正确的角色和索引:

import QtQuick 2.10
import QtQuick.Controls 2.0 as QQC2
import QtQuick.Controls 1.4 as QQC1
import QtQuick.Layouts 1.3

QQC2.ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ColumnLayout {
        anchors.fill: parent
        Repeater {
            model: 2
            QQC1.TableView {
                Layout.fillWidth: true
                Layout.fillHeight: true
                QQC1.TableViewColumn {
                    title: "Parameter Name"
                    role: "one"
                }
                QQC1.TableViewColumn {
                    title: "Value"
                    role: "two"
                    delegate: Loader {
                        property var modelTwo: model.two
                        sourceComponent: typeof(model.two) ==='boolean' ? checkBoxDelegate : stringDelegate
                        function updateValue(value) {
                            model.two = value;
                        }
                    }
                }
                model: myModel
            }
        }
    }

    Component {
        id: checkBoxDelegate
        QQC1.CheckBox {
            text: modelTwo
            checked: modelTwo
            onCheckedChanged: {
                updateValue(checked);
                checked = Qt.binding(function () { return modelTwo; }); // this is needed only in QQC1 to reenable the binding
            }
        }
    }

    Component {
        id: stringDelegate
        TextEdit {
            text: modelTwo
            onTextChanged: updateValue(text)
        }
    }
}
如果这仍然太冗长,并且对您(对我来说)来说不够明确,您可以使用以下方法,其中大部分逻辑都在
加载程序中,而specifics委托人只需告知应该从哪个属性设置和更新值:

delegate: Loader {
    id: loader
    sourceComponent: typeof(model.two) ==='boolean' ? checkBoxDelegate : stringDelegate
    Binding {
        target: loader.item
        property: "editProperty"
        value: model.two
    }
    Connections {
        target: loader.item
        onEditPropertyChanged: model.two = loader.item.editProperty
    }
}

//...

Component {
    id: checkBoxDelegate
    QQC1.CheckBox {
        id: checkbox
        property alias editProperty: checkbox.checked
        text: checked
    }
}

Component {
    id: stringDelegate
    TextEdit {
        id: textEdit
        property alias editProperty: textEdit.finishedText // you can even use a custom property
        property string finishedText
        text: finishedText
        onEditingFinished: finishedText = text
    }
}

“”可能重复谢谢,updateValue函数正在工作。但是,你能解释一下为什么你封锁了信号吗?另外,是否真的无法访问qml中的角色名称?它应该是
updateValue(row,…)
,而不是
updateValue(tableView2.row,…)
。您不应该阻止信号,这会导致未调用
dataChanged
,如果您有其他视图连接到同一模型,这是一个问题。至于检索行号,只需使用
model.index
styleData.row
从加载器委托获取即可。
import QtQuick 2.10
import QtQuick.Controls 2.0 as QQC2
import QtQuick.Controls 1.4 as QQC1
import QtQuick.Layouts 1.3

QQC2.ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ColumnLayout {
        anchors.fill: parent
        Repeater {
            model: 2
            QQC1.TableView {
                Layout.fillWidth: true
                Layout.fillHeight: true
                QQC1.TableViewColumn {
                    title: "Parameter Name"
                    role: "one"
                }
                QQC1.TableViewColumn {
                    title: "Value"
                    role: "two"
                    delegate: Loader {
                        property var modelTwo: model.two
                        sourceComponent: typeof(model.two) ==='boolean' ? checkBoxDelegate : stringDelegate
                        function updateValue(value) {
                            model.two = value;
                        }
                    }
                }
                model: myModel
            }
        }
    }

    Component {
        id: checkBoxDelegate
        QQC1.CheckBox {
            text: modelTwo
            checked: modelTwo
            onCheckedChanged: {
                updateValue(checked);
                checked = Qt.binding(function () { return modelTwo; }); // this is needed only in QQC1 to reenable the binding
            }
        }
    }

    Component {
        id: stringDelegate
        TextEdit {
            text: modelTwo
            onTextChanged: updateValue(text)
        }
    }
}
delegate: Loader {
    id: loader
    sourceComponent: typeof(model.two) ==='boolean' ? checkBoxDelegate : stringDelegate
    Binding {
        target: loader.item
        property: "editProperty"
        value: model.two
    }
    Connections {
        target: loader.item
        onEditPropertyChanged: model.two = loader.item.editProperty
    }
}

//...

Component {
    id: checkBoxDelegate
    QQC1.CheckBox {
        id: checkbox
        property alias editProperty: checkbox.checked
        text: checked
    }
}

Component {
    id: stringDelegate
    TextEdit {
        id: textEdit
        property alias editProperty: textEdit.finishedText // you can even use a custom property
        property string finishedText
        text: finishedText
        onEditingFinished: finishedText = text
    }
}