2014-03-07 54 views
2

我試圖執行以下的事情:是否可以使用QAbstractTableModel與QtQuick.Controls的TableView?

有2d值的表。我需要實現UI來查看數據並對其進行編輯。 爲了簡化UI和來自後端的表更新的編輯之間的同步,我希望模型能夠存儲未提交的編輯值並公開一些方法來接受/拒絕待處理的更改。

據我瞭解,這是相當容易QtWidgets +車型做的事:上QAbstractTableModel

基本型號。 添加一些額外的角色,用於存儲/查詢掛起的更改等 使用QTableView中使用自定義項目的委託,可以查詢模型細胞是否可編輯,顯示未提交的修改等

但我疑惑如何實現它QtQuick.Controls.TableView。 從我的實驗中,TableView不能與QAbstractTableModel一起工作 - 它遍歷模型的第一列並使用角色來模擬第二維。

有沒有辦法使TableView正確工作與QAbstractTableModel? 作爲替代方案 - 我可以將模型更改爲使用列的角色,但我不確定如何處理單元格數據的其他方面(修改標誌,未定義值等)。我到目前爲止唯一的想法是返回每個單元格的複合(字典)值。例如。將QMap或QJsonObject作爲「cell」的值返回並在QML端進行解釋。

還有其他方法可以做到嗎? 如果我決定實現我的第二個解決方案 - QMap或QJsonObject,會更有效嗎?

回答

1

這是一個例子也許會幫助你希望

假設我們有一個包含表「MYTABLE」有三列「NOM」(文本),「prenom」(文本)和「形象」的SQLite數據庫(URL文本)

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

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


     } 

     } 
+0

感謝這樣詳細的答覆,但從我在那裏看到的,你基本上確認了我在問題中寫的內容。在您的data()函數中,您基本上將行索引+角色重新映射到底層Qt表模型中的行和列。 – Usov

+0

是的,你知道,主要的事情是**角色**,** data()**和**角色()** functions.if你需要更多的幫助,我在這裏。祝你好運 – Redanium