HorizontalHeaderView 未调用 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
}
// ...
根据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
}
// ...