C++ 通过带有自定义委托的TableView编辑QStandardItemModel
我有一个QStandarItemModel,通过QML表格视图显示 模型如下: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
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
}
}