QtQuick TableView无法使用C ++ - QAbstractTableModel

时间:2014-12-26 09:49:45

标签: qt tableview qml

我试图让Qt模型/视图架构使用QML-View,但无论出于何种原因它只能部分工作。

什么有效:

  • rowCount时
  • 数据
  • 角色名

不工作:

  • columnCount(该方法被调用,但似乎没有效果,只要它是> 0)
  • headerData(这实际上应该设置列标题吗?所有示例都在QML中设置标题)
  • 标志
  • 使用setData

我想要做的事情(已经有几个星期了),就是创建一个带有TableView和C ++模型的简单ApplicationView,它可以被视图编辑。

现在只能选择整行,而不是单个单元格。表格数据似乎根本不可编辑。谁能给我一个提示?

main.qml

import QtQuick 2.3
import QtQuick.Controls 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    TableView {
        model: theModel
        TableViewColumn {
            role: "nameRole"
            width: 75
        }
        TableViewColumn {
            role: "ageRole"
            width: 50
        }
    }
}

ModelItem.hpp

#ifndef MODELITEM
#define MODELITEM

#include <QString>

struct ModelItem {
    ModelItem(QString name_, int age_)
        : name(name_), age(age_) {}
    QString name;
    int age;
};

#endif // MODELITEM

TableModel.hpp

#ifndef TABLEMODEL_HPP
#define TABLEMODEL_HPP

#include <QAbstractTableModel>
#include "ModelItem.hpp"

class TableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    TableModel(QObject *parent = 0);

    //works
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;

    //does not work
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

    QHash<int, QByteArray> roleNames() const;
    enum Roles {
        NameRole = Qt::UserRole + 1,
        AgeRole
    };

    Qt::ItemFlags flags(const QModelIndex &index) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);

private:
    QList<ModelItem*> items;
};

#endif // TABLEMODEL_HPP

TableModel.cpp

#include "TableModel.hpp"

TableModel::TableModel(QObject *parent)
    : QAbstractTableModel(parent) {
    items.append(new ModelItem("Hugo",33));
    items.append(new ModelItem("Egon",34));
    items.append(new ModelItem("Balder",66));
    qDebug("TableModel initialisiert");
}


int TableModel::columnCount(const QModelIndex &parent) const {
    Q_UNUSED(parent);
    qDebug("columnCount");
    return 2;
}

int TableModel::rowCount(const QModelIndex &parent) const {
    Q_UNUSED(parent);
    qDebug("rowCount");
    return items.count();
}

QVariant TableModel::data(const QModelIndex &index, int role) const {
    qDebug("data");
    switch (role) {
        case NameRole: return items[index.row()]->name;
        case AgeRole: return items[index.row()]->age;
    }
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {
    qDebug("headerData");
    switch (role) {
        case NameRole: return "1";
        case AgeRole: return "2";
    };
    return QVariant();
}

QHash<int, QByteArray> TableModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[NameRole] = "nameRole";
    roles[AgeRole] = "ageRole";
    qDebug("roleNames initialised");

    return roles;
}

Qt::ItemFlags TableModel::flags(const QModelIndex &index) const {
    qDebug("--flags called--");
    return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}

bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    qDebug("setData called");
    switch (role) {
        case NameRole: items[index.row()]->name = value.toString();
        case AgeRole: items[index.row()]->age = value.toInt();
    }
    emit dataChanged(index, index);
    return true;
}

的main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "TableModel.hpp"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    TableModel model;
    engine.rootContext()->setContextProperty("theModel", &model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

2 个答案:

答案 0 :(得分:9)

QAbstractItemModel::index方法中调用了

columnCountrowCount,在data方法之前由TableView调用。

QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent) const
{
    return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
}

bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
{
    if (row < 0 || column < 0)
        return false;
    return row < rowCount(parent) && column < columnCount(parent);
}

columnCount无效,只要它是&gt; 0,因为TableView调用index方法,列总是等于0。

headerDataflags没有影响QML TableView。您只能在QML端设置标题。要创建可编辑的TableView,您应该实现自定义itemDelegate

<强> main.qml

ApplicationWindow {
    visible: true
    id: root
    Component {
        id: editableDelegate
        Item {
            Text {
                width: parent.width
                anchors.margins: 4
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                elide: styleData.elideMode
                text: styleData.value !== undefined ? styleData.value : ""
                color: styleData.textColor
                visible: !styleData.selected
            }
            Loader {
                id: loaderEditor
                anchors.fill: parent
                anchors.margins: 4
                Connections {
                    target: loaderEditor.item
                    onEditingFinished: {
                        theModel.setData(styleData.row, styleData.column, loaderEditor.item.text)
                    }
                }
                sourceComponent: styleData.selected ? editor : null
                Component {
                    id: editor
                    TextInput {
                        id: textinput
                        color: styleData.textColor
                        text: styleData.value
                        MouseArea {
                            id: mouseArea
                            anchors.fill: parent
                            hoverEnabled: true
                            onClicked: textinput.forceActiveFocus()
                        }
                    }
                }
            }
        }
    }
    TableView {
        id: table
        anchors.fill: parent
        model: theModel
        itemDelegate: editableDelegate;
        TableViewColumn {
            role: "nameRole"
            width: 75
            title: "name"
        }
        TableViewColumn {
            role: "ageRole"
            width: 50
            title: "age"
        }
    }
}

要将更改应用于模型,您应该实现setData方法,如下所示:

<强> TableModel.h

bool setData(const QModelIndex &index, const QVariant &value, int role) {
    switch (role) {
        case NameRole: items[index.row()]->name = value.toString(); break;
        case AgeRole: items[index.row()]->age = value.toInt(); break;
    }
    emit dataChanged(index, index);
    return true;
}

Q_INVOKABLE bool setData(int row, int column, const QVariant value)
{
    int role = Qt::UserRole + 1 + column;
    return setData(index(row,0), value, role);
}

答案 1 :(得分:2)

以上答案很好地涵盖了一些事情。我只想添加几个注释: