一、概述
功能:?實現一個查詢學生信息的表格,有學號、性別、年齡、班級和分數共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
):