是否可以将QAbstractTableModel与QtQuick.Controls中的TableView一起使用? [英] Is it possible to use QAbstractTableModel with TableView from QtQuick.Controls?
问题描述
我正在尝试实现以下目标:
I’m trying to implement following thing:
有带有值的2d表.我需要实现UI来查看和编辑数据. 为了简化来自UI的编辑和来自后端的表更新之间的同步,我希望模型存储未提交的编辑值,并公开一些方法来接受/拒绝未决的更改.
There is 2d table with values. I need to implement UI for viewing data and editing it. To simplify synchronisation between edits from UI and table updates coming from the back-end, I want model to store uncommitted edited values and expose a couple of methods to accept/reject pending changes.
据我了解,使用QtWidgets +模型可以轻松做到这一点:
From what I understand this is reasonably easy to do with QtWidgets + models:
基于QAbstractTableModel的模型. 添加一些额外的角色来存储/查询未决的更改等. 将QTableView与自定义项目委托一起使用,可以查询模型是否可编辑单元格,显示未提交的更改等.
Base model on QAbstractTableModel. Add a few extra roles for storing/querying pending changes, etc. Use QTableView with custom item delegate, which can query model whether cell is editable, show uncommitted changes, etc.
但是我对如何实现QtQuick.Controls.TableView感到困惑. 根据我的实验,TableView不能与QAbstractTableModel一起使用-会在模型的第一列上进行迭代,并使用角色来模拟第二维.
But I’m puzzled about how to implement it QtQuick.Controls.TableView. From my experiments, TableView doesn’t work with QAbstractTableModel — it iterates over the first column of the model and uses roles to simulate second dimension.
有没有一种方法可以使TableView与QAbstractTableModel一起正常使用? 或者,我可以更改模型以对列使用角色,但是我不确定如何处理单元格数据的其他方面(修改的标志,未提交的值等).到目前为止,我唯一的想法是为每个单元格返回复合(字典)值.例如.返回QMap或QJsonObject作为单元格"的值,并在QML端对其进行解释.
Is there a way to make TableView work with QAbstractTableModel correctly? As an alternative — I can change model to use roles for columns, but I’m not sure how to handle other aspects of cell data (modified flag, uncommited value, etc.). The only idea I have so far is to return composite (dictionary) value for each cell. E.g. return QMap or QJsonObject as a value of "cell" and interpret it on QML side.
还有其他方法可以做到吗? 如果我决定实施第二个解决方案(QMap或QJsonObject),哪个会更有效?
Are there any other ways to do it? What’s more effective if I decide to implement my second solution — QMap or QJsonObject?
推荐答案
这是一个示例,也许会对您有所帮助
This is an example maybe it'll help you hopefully
假设我们有一个sqlite数据库,其中包含一个表"mytable",该表具有三列"nom"(文本),"prenom"(文本)和"image"(URL作为文本)
Suppose we have sqlite database containing a table "mytable" with three columns "nom" (text),"prenom"(text) and "image"(url as text)
--------------------------- PRESENCEMODEL.h
#include <QSqlTableModel>
typedef QHash<int,QByteArray> qMyHash ;
class PresenceModel : public QSqlTableModel {
Q_OBJECT
Q_PROPERTY(QStringList dictionary READ dictionary NOTIFY dictionaryChanged)
Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
Q_PROPERTY(qMyHash roles READ roles NOTIFY rolesChanged)
public:
PresenceModel(QSqlDatabase, QObject* parent = 0);
void generateRoleNames();
QString filterString() const { return p_filterString; }
void setFilterString(const QString&);
Q_INVOKABLE QStringList getData(int currentRow);
QVariant data(const QModelIndex&, int role) const;
Q_INVOKABLE void insert(const QString& url, const QString& title);
void populate();
QHash<int, QByteArray> roleNames() const;
Q_INVOKABLE void p_setTable(const QString &tableName);
QStringList dictionary() const;
void setDictionary(const QStringList &value);
QHash<int, QByteArray> roles() const;
Q_SIGNALS:
void dataChanged();
void gotData();
void rolesChanged();
private:
enum ColumnRH {
nom= Qt::UserRole + 1,
prenom= Qt::UserRole + 2,
image= Qt::UserRole + 3
};
QHash<int, QByteArray> p_roles;
QString p_filterString;
QStringList p_dictionary;
};
--------------------------- PRESENCEMODEL.cpp
--------------------------- PRESENCEMODEL.cpp
#include "presencemodel.h"
#include <QtCore/QDateTime>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>
#include <QDebug>
PresenceModel::PresenceModel(QSqlDatabase database, QObject *parent)
: QSqlTableModel(parent, database)
{
}
void PresenceModel::generateRoleNames()
{
p_roles[nom] = "nom";
p_roles[prenom] = "prenom";
p_roles[image] = "image";
}
void PresenceModel::populate()
{
select();
}
void PresenceModel::insert(const QString& url, const QString& title)
{
}
QVariant PresenceModel::data(const QModelIndex& index, int role) const
{
if (role < Qt::UserRole)
return QSqlQueryModel::data(index, role);
const int columnId = role - Qt::UserRole;
const QModelIndex modelIndex = createIndex(index.row(), columnId-1);
return QSqlTableModel::data(modelIndex, Qt::DisplayRole);
}
QStringList PresenceModel::getData(int currentRow)
{
QStringList rowDataList;
for (int i=0;i<columnCount();i++)
rowDataList.append(data(this->index(currentRow,i),Qt::DisplayRole).toString());
emit gotData();
return rowDataList;
}
QHash<int, QByteArray> PresenceModel::roleNames() const
{
return p_roles;
}
QHash<int, QByteArray> PresenceModel::roles() const
{
return roleNames();
}
--------------------------- main.cpp
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QSqlDatabase m_database = QSqlDatabase::addDatabase("QSQLITE");
m_database.setDatabaseName("/.../mydatabase.sqlite");
PresenceModel *p_pModel= new PresenceModel(m_database);
p_pModel->setTable("mytable");
m_database.open();
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("ppModel", (PresenceModel*) p_pModel);
engine.load(QUrl("qrc:/main.qml"));
return app.exec();
}
QML
--------------------------- main.qml
Rectangle {
Component.OnCompleted : ppModel.populate()
TableView{
id:tableview_actes
TableViewColumn{ role: "nom" ; title: "nom" ; width: 330 }
TableViewColumn{ role: "prenom" ; title: "prénom" ; width: 65}
TableViewColumn{ role: "image" ; title: "Photo" ; width:65}
model:ppModel
onCurrentRowChanged: {
var list= myModel.getData(currentRow) // invoke c++ function
console.log(list[0])
}
Listview{
model:ppModel
delegate:
Item {
Text{
text: nom + " " +prenom // our roles
}
Image{
source : image // image : url in our table
}
}
}
}
}
这篇关于是否可以将QAbstractTableModel与QtQuick.Controls中的TableView一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!