У меня есть QStandardItemModel, который я отображаю в виде таблицы 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;
}
};
и вот как модель отображается с использованием пользовательских делегатов:
TableView {
id: tableView2
x: 69
y: 316
width: 318
height: 150
TableViewColumn {
title: "Parameter Name"
role: "one"
}
TableViewColumn {
title: "Value"
role: "two"
delegate: myDelegate
}
model: myTestModel
}
Component {
id: myDelegate
Loader {
property var roleTwo: model.two
sourceComponent: if(typeof(roleTwo)=='boolean') {
checkBoxDelegate}
else { stringDelegate}
}
}
Component {
id: checkBoxDelegate
CheckBox{text: roleTwo}
}
Component {
id: stringDelegate
TextEdit {text: roleTwo}
}
Я заполнил модель следующим образом:
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);
Как сделать модель редактируемой, чтобы с помощью флажка или редактирования текст передавался обратно в модель?
Изменить: я попытался следовать предложению в QML TableView, когда щелкнул, отредактировал данные (например, excel) и использовал модель набора:
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_INVOKABLE
. Поскольку обновление отображается в представлении, нет необходимости уведомлять его, кроме как вызвать странные события.
для получения строки мы используем геометрию и rowAt()
метод TableView
.
Ниже приведен пример:
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"
main.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")
TableView {
id: tableView2
anchors.fill: parent
TableViewColumn {
title: "Parameter Name"
role: "one"
}
TableViewColumn {
title: "Value"
role: "two"
delegate: myDelegate
}
model: myTestModel
}
Component {
id: myDelegate
Loader {
property var roleTwo: model.two
sourceComponent: typeof(roleTwo)=='boolean'? checkBoxDelegate: stringDelegate
}
}
Component {
id: checkBoxDelegate
CheckBox{
checked: roleTwo
onCheckedChanged:{
var pos = mapToGlobal(0, 0)
var p = tableView2.mapFromGlobal(pos.x, pos.y)
var row = tableView2.rowAt(p.x, p.y)
if(row >= 0)
myTestModel.updateValue(tableView2.row, checked, "two")
}
}
}
Component {
id: stringDelegate
TextField {
text: roleTwo
onEditingFinished: {
var pos = mapToGlobal(0, 0)
var p = tableView2.mapFromGlobal(pos.x, pos.y)
var row = tableView2.rowAt(p.x, p.y)
if(row >= 0)
myTestModel.updateValue(tableView2.row, text, "two")
}
}
}
}
Полный пример можно найти по следующей ссылке .
Эта статья взята из Интернета, укажите источник при перепечатке.
Если есть какие-либо нарушения, пожалуйста, свяжитесь с[email protected] Удалить.
я говорю два предложения