一、概述
功能: 实现一个查询学生信息的表格,有学号、性别、年龄、班级和分数共5列,针对最后一列分数实现委托代理,要求能编辑和查看该分数列。
QTableView实现视图展示ui
Model负责数据的构造
Delegate是委托,可针对某列数据做自定义扩展
使用的qt控件如下:
- QTableView
- StudentTableModel继承自QAbstractTableModel
- ScoreDelegate继承自QStyledItemDelegate
二、具体代码
studenttablemodel.h
#ifndef STUDENTTABLEMODEL_H
#define STUDENTTABLEMODEL_H#include <QAbstractTableModel>
#include <QObject>class StudentTableModel : public QAbstractTableModel
{Q_OBJECT
public:explicit StudentTableModel(QObject *parent = nullptr);int rowCount(const QModelIndex &parent = QModelIndex()) const override;int columnCount(const QModelIndex &parent = QModelIndex()) const override;QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;QVariant headerData(int section, Qt::Orientation orientation,int role = Qt::DisplayRole) const override;bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;Qt::ItemFlags flags(const QModelIndex &index) const override;private:QVector<QVector<QVariant>> m_data; // 数据存储
};#endif // STUDENTTABLEMODEL_H
studenttablemodel.cpp
#include "studenttablemodel.h"StudentTableModel::StudentTableModel(QObject *parent): QAbstractTableModel{parent}
{// 初始化示例数据m_data = {{"1001", "male", 18, "class_01", 85},{"1002", "female", 19, "class_02", 92},{"1003", "male", 20, "class_03", 78}};
}int StudentTableModel::rowCount(const QModelIndex &parent) const
{Q_UNUSED(parent);return m_data.size();
}int StudentTableModel::columnCount(const QModelIndex &parent) const
{Q_UNUSED(parent);return 5; // 学号、性别、年龄、班级、分数
}QVariant StudentTableModel::data(const QModelIndex &index, int role) const
{if(!index.isValid()) return QVariant();if (role == Qt::DisplayRole || role == Qt::EditRole) {return m_data[index.row()][index.column()];}return QVariant();
}QVariant StudentTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {switch (section) {case 0: return "id";case 1: return "sex";case 2: return "age";case 3: return "class";case 4: return "score";}}return QVariant();
}bool StudentTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{if (role == Qt::EditRole && index.isValid()) {m_data[index.row()][index.column()] = value;emit dataChanged(index, index); // 通知视图更新return true;}return false;
}Qt::ItemFlags StudentTableModel::flags(const QModelIndex &index) const
{auto flags = QAbstractTableModel::flags(index);if (index.column() == 4) // 分数列可编辑flags |= Qt::ItemIsEditable;return flags;
}
scoredelegate.h
#ifndef SCOREDELEGATE_H
#define SCOREDELEGATE_H#include <QObject>
#include <QStyledItemDelegate>class ScoreDelegate : public QStyledItemDelegate
{Q_OBJECT
public:explicit ScoreDelegate(QObject *parent = nullptr);QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const override;void setEditorData(QWidget *editor, const QModelIndex &index) const override;void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const override;
};#endif // SCOREDELEGATE_H
#include "scoredelegate.h"#include <QSpinBox>ScoreDelegate::ScoreDelegate(QObject *parent): QStyledItemDelegate{parent}
{}QWidget *ScoreDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{if (index.column() == 4) { // 仅对分数列生效QSpinBox *editor = new QSpinBox(parent);editor->setRange(0, 100);editor->setFrame(false);return editor;}return QStyledItemDelegate::createEditor(parent, option, index);
}void ScoreDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{if (index.column() == 4) {int value = index.model()->data(index, Qt::EditRole).toInt();QSpinBox *spinBox = qobject_cast<QSpinBox*>(editor);spinBox->setValue(value);} else {QStyledItemDelegate::setEditorData(editor, index);}
}void ScoreDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{if (index.column() == 4) {QSpinBox *spinBox = qobject_cast<QSpinBox*>(editor);spinBox->interpretText();model->setData(index, spinBox->value());} else {QStyledItemDelegate::setModelData(editor, model, index);}
}
widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);model = new StudentTableModel(this);scoreDelegate = new ScoreDelegate(this);ui->tableView->setModel(this->model);ui->tableView->setItemDelegateForColumn(4, scoreDelegate);// 表格样式设置ui->tableView->verticalHeader()->hide();ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);ui->tableView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);//手动设置show显示ui->tableView->show();
}
三、遇到问题总结
1、QTableView展示不出来,model+tableview为局部变量
当构造函数执行结束时,这两个对象会被自动销毁。即使调用了 tableView.show()
,窗口会短暂显示,但对象销毁后视图也随之消失,因此实际看不到表格
解决方案:
将 tableView
和 model
提升为类的成员变量,确保其生命周期与窗口一致:
2、 视图未嵌入父窗口布局
问题分析:
- 即使解决了生命周期问题,若
tableView
未添加到窗口布局中,它可能因尺寸为0或位置错误而不可见。 - 你的代码中
tableView
是独立创建的,未关联到ui
生成的界面布局中。
解决方案:
将 tableView
添加到窗口的布局管理器中(例如使用 QVBoxLayout
):