QtQuick TableView无法使用C++ - QAbstractTableModel

Mar*_*c Q 10 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

Mee*_*fte 9

columnCountrowCountQAbstractItemModel :: index方法中调用,该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);
}
Run Code Online (Sandbox Code Playgroud)

columnCount没有效果,只要它> 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"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要将更改应用于模型,您应该实现该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);
}
Run Code Online (Sandbox Code Playgroud)