Horizo​​ntalHeaderView 未调用 QAbstractTableModel 的 headerData() child

HorizontalHeaderView not calling headerData() of QAbstractTableModel's child

根据HorizontalHeaderView's doc,如果模型是QAbstractTableModel,那么header会显示模型的横向headerData();否则,模型的数据()。但就我而言,它甚至没有调用它。但是小部件模块中的 QTableView 似乎工作得很好。

这是我的 main.qml:-

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    id: root

    HorizontalHeaderView {
        id: header
        syncView: tb
        anchors.top: parent.top
        //        model: KoolModel // specify model explicitly also does not work 
        delegate: Button {
            text: display
        }
    }
    TableView {
        id: tb
        width: parent.width
        height: parent.height - header.height
        anchors.top: header.bottom

        onWidthChanged: forceLayout()

        model: KoolModel
        columnWidthProvider: function (_) {
            return root.width / 3
        }
        delegate: Frame {
            Label {
                text: display
                anchors.centerIn: parent
            }
        }
    }
}

这是我的模型:-

#include <QApplication>
#include <QGuiApplication>
#include <QTableView>

#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <QAbstractTableModel>
#include <QString>
#include <map>

class Exams : public QAbstractTableModel {

private:
    struct DS {
        QString title;
        unsigned int marks;
        int state;
        std::vector<int>* questions = nullptr;
    };

    //id and exams
    std::map<int, DS> exams;

public:
    Exams()
    {
        for (int i = 0; i < 10; i++) {
            DS exam { "Exam" + QString::number(i), 0, (i * 3) / 2, nullptr }; // fill with garbage data for now
            exams[i] = exam;
        }
    }

    int rowCount(const QModelIndex& parent) const override
    {
        return exams.size();
    }

    int columnCount(const QModelIndex& parent) const override
    {
        return 3;
    }

    QVariant data(const QModelIndex& index, int role) const override
    {
        if (role == Qt::DisplayRole) {
            if (index.column() == 0)
                return exams.at(index.row()).title;
            else if (index.column() == 1)
                return exams.at(index.row()).marks;
            else if (index.column() == 2)
                return exams.at(index.row()).state;
        }
        qDebug() << "oops";
        return QVariant();
    }

    QVariant headerData(int section, Qt::Orientation orientation, int role) const override
    {
        qDebug() << "headerData is at least called";
        if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
            switch (section) {
            case 0:
                return QString("Title");
            case 1:
                return QString("Marks");
            case 2:
                return QString("state");
            }
        }
        return QVariant();
    }

    QHash<int, QByteArray> roleNames() const override
    {
        return { { Qt::DisplayRole, "display" } };
    }
};

int main(int argc, char* argv[])
{
    Exams exams;

    // widgets seems to work
    //    QApplication app(argc, argv);
    //    QTableView widget;
    //    widget.setModel(&exams);
    //    widget.show();

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("KoolModel", &exams);
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    engine.load(url);

    return app.exec();
}

问题是由 Button 的 display 属性 和角色之间的命名冲突引起的。解决方案是通过模型显式访问角色:

// ...
delegate: Button {
    text: <b>model.</b>display
}
// ...