北京微网站设计,沈阳网页排名优化方法,sun v2.1 wordpress主题,搜狐新闻手机网前言
此篇博客写的小项目与之前写的一篇《QTableWidget》类似#xff0c;只是使用了不同的方法进行实现。但是推荐使用此篇播放的方法#xff1b;因为高效#xff0c;低耗能。
当然#xff0c;项目中还涉及到使用委托添加控件#xff0c;即在单元格中添加控件#xff0…前言
此篇博客写的小项目与之前写的一篇《QTableWidget》类似只是使用了不同的方法进行实现。但是推荐使用此篇播放的方法因为高效低耗能。
当然项目中还涉及到使用委托添加控件即在单元格中添加控件使其双击后才显示出来。 具体操作请看此篇博客使用委托QItemDelegate 于 QTableView单元格添加控件。
QAbstractTableModel的父类QABstractItemModel他从父类中继承下来了大量方法我们需要使用该类的话也是需要继承与他(QAbstractTableModel)然后进行重写其里面的方法。
项目实现效果
总体来说继承于QAbstractTableModel实现起来还是蛮容易的重写方法根据自己的项目需求进行编写对于数据的管理也是挺友好的。 相比于QTableWidgetQAbstractTableModel使用的内存更少数据管理更方便。 定义
需要包含头文件#include QAbstractTableModel 继承自QAbstractTableModel class TableModel : public QAbstractTableModel {
public:// ...private:// 16列对应16个链表存储数据QStringList m_No;QStringList m_Reference;QStringList m_X;QStringList m_Y;QStringList m_Z;QStringList m_R;QStringList m_Part;QStringList m_Feeder;QStringList m_Nozzle;QStringList m_HD;QMapint, Qt::CheckState m_CS;QStringList m_CY;QMapint, Qt::CheckState m_SK;QStringList m_AR;QMapint, Qt::CheckState m_FID;QStringList m_BL;// 存储水平方向头数据QStringList m_HorizontalHead;
}这里我们需求是有16列所以得定义16个数据变量来存储。 重写以下方法 // 返回行个数
virtual int rowCount(const QModelIndex parent QModelIndex()) const override;
// 返回列个数
virtual int columnCount(const QModelIndex parent QModelIndex()) const override;
// 返回头文本
virtual QVariant headerData(int section, Qt::Orientation orientation, int role Qt::DisplayRole) const override;
// 返回索引数据
virtual QVariant data(const QModelIndex index, int role Qt::DisplayRole) const override;
// 返回模型索引
virtual QModelIndex index(int row, int column, const QModelIndex parent QModelIndex()) const override;
// 返回模型索引的编辑方式
virtual Qt::ItemFlags flags(const QModelIndex index) const override;
// 设置模型索引数据
virtual bool setData(const QModelIndex index, const QVariant value, int role Qt::EditRole) override;
// 插入行
virtual bool insertRows(int row, int count, const QModelIndex parent QModelIndex()) override;
// 删除行
virtual bool removeRows(int row, int count, const QModelIndex parent QModelIndex()) override;实现方法体 (1). rowCount 此方法的作用见名之意此方法是返回行的个数。 // 返回行个数
int TableModel::rowCount(const QModelIndex parent) const {// 某一列的数据个数即是行数return this-m_No.size();
}(2). columnCount 此方法的作用见名之意此方法是返回列的个数。 // 返回列个数
int TableModel::columnCount(const QModelIndex parent) const {
// 项目代码中我们再头文件里写了一个对于列表头索引的枚举所以这里直接使用枚举的个数来进行返回。return COLUMN_HEAD_INDEX::COLUMN;
}(3). headerData 此方法的作用设置表头文本并返回文本内容 // 返回头文本
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {if (role ! Qt::DisplayRole) // 返回一个默认数据的表头return QAbstractTableModel::headerData(section, orientation, role);// 仅仅只是返回水平方向的表头if (orientation Qt::Orientation::Horizontal) {return this-m_HorizontalHead[section];}return QAbstractTableModel::headerData(section, orientation, role);
}根据参数role角色判定再进行下一步操作。 (4). data 此方法的作用返回索引的数据。 // 返回索引数据
QVariant TableModel::data(const QModelIndex index, int role) const {// 不存在则返回默认if (!index.isValid()) return QVariant();// 如果角色为显示和编辑模式if (role Qt::DisplayRole || role Qt::EditRole) {// 此处省略一万行代码...// 否则如果角色为选中模式即多选框} else if (role Qt::CheckStateRole) {// 此处省略一万行代码...}return QVariant();
}省略处的代码将在下方进行展示。每个参数都有其特殊意义。 (5). index 此方法的作用返回行和列对应单元格的索引。 // 返回模型索引
QModelIndex TableModel::index(int row, int column, const QModelIndex parent) const {// 行和列的合法性检查if (row 0 || row this-m_No.size() || column 0 || column COLUMN_HEAD_INDEX::COLUMN) {return QModelIndex();}// 此处省略一万行代码...// 新建一个索引并绑定指针数据返回指针数据可有可无// return createIndex(row, column);return createIndex(row, column);
}省略处的代码将在下方进行展示。根据行和列新建一个索引并返回。 (6). flags 此方法的作用根据索引返回其的编辑模式。 // 返回模型索引的编辑方式
Qt::ItemFlags TableModel::flags(const QModelIndex index) const {if (!index.isValid()) {// 返回用户可以与界面进行交互return Qt::ItemIsEnabled | Qt::ItemIsSelectable;}// 此处省略一万行代码... // 返回用户可以进行编辑// return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}省略处的代码将在下方进行展示。根据索引的列返回编辑方式。 (7). setData 此方法的作用将参数value索引存入对应列的数据变量中。 // 设置模型索引数据
bool TableModel::setData(const QModelIndex index, const QVariant value, int role) {if (index.isValid() role Qt::EditRole) {// 此处省略一万行代码...// 设置完成后发射信号告诉视图数据有修改emit dataChanged(index, index); // 参数是左上角和右下角的模型索引这里是相同的return true;} else if (index.isValid() role Qt::CheckStateRole) {// 此处省略一万行代码...// 设置完成后发射信号告诉视图数据有修改emit dataChanged(index, index); // 参数是左上角和右下角的模型索引这里是相同的return true;}return false;
}省略处的代码将在下方进行展示。存储完后得发射信号告诉视图数据有修改。 (8). insertRows 此方法的作用插入一行或多行数据。 // 插入行 参数插入的位置插入的行数父项的模型索引
bool TableModel::insertRows(int row, int count, const QModelIndex parent) {// 如果插入零行则返回false表示插入失败if (count 0) return false;// 没有父类if (!parent.isValid()) {// 从row开始插入行直到row count - 1处beginInsertRows(QModelIndex(), row, row count - 1);// 有父类} else {// 从row开始插入行直到row count - 1处beginInsertRows(parent, row, row count - 1);}// 按照位置在链表对应位置进行插入数据for (int addCount 0; addCount count; addCount) {this-m_No.insert(row addCount, );this-m_Reference.insert(row addCount, );this-m_X.insert(row addCount, );this-m_Y.insert(row addCount, );this-m_Z.insert(row addCount, );this-m_R.insert(row addCount, );this-m_Part.insert(row addCount, );this-m_Feeder.insert(row addCount, );this-m_Nozzle.insert(row addCount, );this-m_HD.insert(row addCount, );this-m_CS.insert(row addCount, Qt::CheckState::Unchecked);this-m_CY.insert(row addCount, );this-m_SK.insert(row addCount, Qt::CheckState::Unchecked);this-m_AR.insert(row addCount, );this-m_FID.insert(row addCount, Qt::CheckState::Unchecked);this-m_BL.insert(row addCount, );}// 结束插入行endInsertRows();return true;
}使用beginInsertRows()开始插入endInsertRows()结束插入。 插入后存储数据的链表也得对应插入空数据或者插入默认数据这才能保证数据的同步性。 (9). removeRows 此方法的作用删除一行或者多行数据。 // 删除行
bool TableModel::removeRows(int row, int count, const QModelIndex parent) {if (count 0) return false;if (!parent.isValid()) {beginRemoveRows(QModelIndex(), row, row count - 1);} else {beginInsertRows(parent, row, row count - 1);}// 按照位置在链表对应位置进行移除数据for (int removeCount 0; removeCount count; removeCount) {this-m_No.removeAt(row);this-m_Reference.removeAt(row);this-m_X.removeAt(row);this-m_Y.removeAt(row);this-m_Z.removeAt(row);this-m_R.removeAt(row);this-m_Part.removeAt(row);this-m_Feeder.removeAt(row);this-m_Nozzle.removeAt(row);this-m_HD.removeAt(row);this-m_CS.remove(row removeCount);this-m_CY.removeAt(row);this-m_SK.remove(row removeCount);this-m_AR.removeAt(row);this-m_FID.remove(row removeCount);this-m_BL.removeAt(row);}endRemoveRows();return true;
}使用beginRemoveRows()开始删除endRemoveRows()结束删除。 删除后存储数据的链表也得删除对应的数据这才能保证数据的同步性。
好了到了这里说明前期准备工作已经做得差不多了接下来就可以去使用这个类了。 使用
另外新建类HzcTableEdit
ui文件
再构造函数中new对象将其与TableView进行绑定即可。
TableModel *m_tableModel new TableModel;
ui.tableView-setModel(this-m_tableModel);至于插入、删除等功能实现按钮的槽方法再使用m_tableModel对象调用插入和删除的方法即可具体实现按照具体项目需求即可。
QTableView 零碎知识点
设置水平头文本居中 ui.tableView-horizontalHeader()-setDefaultAlignment(Qt::AlignHCenter);
设置隔行变色 ui.tableView-setAlternatingRowColors(true);
设置最后一列填满表格剩余空间 ui.tableView-horizontalHeader()-setStretchLastSection(true);
设置表格行高 ui.tableView-verticalHeader()-setDefaultSectionSize(30);
设置表格列宽 ui.tableView-setColumnWidth(column, 40);
设置用户可以拖动行 ui.tableView-verticalHeader()-setSectionsMovable(true);
设置固定行高 ui.tableView-verticalHeader()-setSectionResizeMode(QHeaderView::Fixed); ui.tableView-horizontalHeader()-setSectionResizeMode(QHeaderView::Fixed);
设置表头样式表颜色
// 设置行表头背景颜色样式为浅黄色
ui.tableView-horizontalHeader()-setStyleSheet(QHeaderView::section{background:#ffff9b;});
// 设置列表头背景颜色样式为浅蓝色
ui.tableView-verticalHeader()-setStyleSheet(QHeaderView::section{background:#a7fffa;});
// 设置左上角两个表头相交的区域的颜色样式为浅灰色
ui.tableView-setStyleSheet(QTableCornerButton::section{background:#c2c2c2;});全部实现代码
TableModel.h
#pragma once
#include QAbstractTableModel#pragma execution_character_set(utf-8) // qt支持显示中文enum COLUMN_HEAD_INDEX {No 0,Reference 1,X 2,Y 3,Z 4,R 5,Part 6,Feeder 7,Nozzle 8,HD 9,CS 10,CY 11,SK 12,AR 13,FID 14,BL 15,COLUMN 16
};class TableModel : public QAbstractTableModel {public:TableModel(QAbstractTableModel *parent nullptr);~TableModel();// 返回行个数virtual int rowCount(const QModelIndex parent QModelIndex()) const override;// 返回列个数virtual int columnCount(const QModelIndex parent QModelIndex()) const override;// 返回头文本virtual QVariant headerData(int section, Qt::Orientation orientation, int role Qt::DisplayRole) const override;// 返回索引数据virtual QVariant data(const QModelIndex index, int role Qt::DisplayRole) const override;// 返回模型索引virtual QModelIndex index(int row, int column, const QModelIndex parent QModelIndex()) const override;// 返回模型索引的编辑方式virtual Qt::ItemFlags flags(const QModelIndex index) const override;// 设置模型索引数据virtual bool setData(const QModelIndex index, const QVariant value, int role Qt::EditRole) override;// 插入行virtual bool insertRows(int row, int count, const QModelIndex parent QModelIndex()) override;// 删除行virtual bool removeRows(int row, int count, const QModelIndex parent QModelIndex()) override;private:// 16列对应16个链表存储数据QStringList m_No;QStringList m_Reference;QStringList m_X;QStringList m_Y;QStringList m_Z;QStringList m_R;QStringList m_Part;QStringList m_Feeder;QStringList m_Nozzle;QStringList m_HD;QMapint, Qt::CheckState m_CS;QStringList m_CY;QMapint, Qt::CheckState m_SK;QStringList m_AR;QMapint, Qt::CheckState m_FID;QStringList m_BL;// 存储水平方向头数据QStringList m_HorizontalHead;
};TableModel.cpp
#include TableModel.hTableModel::TableModel(QAbstractTableModel *parent) : QAbstractTableModel(parent) {this-m_HorizontalHead.append(No.);this-m_HorizontalHead.append(Reference);this-m_HorizontalHead.append(X);this-m_HorizontalHead.append(Y);this-m_HorizontalHead.append(Z);this-m_HorizontalHead.append(R);this-m_HorizontalHead.append(Part);this-m_HorizontalHead.append(Feeder);this-m_HorizontalHead.append(Nozzle);this-m_HorizontalHead.append(HD);this-m_HorizontalHead.append(CS);this-m_HorizontalHead.append(CY);this-m_HorizontalHead.append(SK);this-m_HorizontalHead.append(AR);this-m_HorizontalHead.append(FID);this-m_HorizontalHead.append(BL);
}TableModel::~TableModel() {}// 返回行个数
int TableModel::rowCount(const QModelIndex parent) const {return this-m_No.size();
}// 返回列个数
int TableModel::columnCount(const QModelIndex parent) const {return COLUMN_HEAD_INDEX::COLUMN;
}// 返回头文本
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {if (role ! Qt::DisplayRole) // 返回一个默认数据的表头return QAbstractTableModel::headerData(section, orientation, role);if (orientation Qt::Orientation::Horizontal) {return this-m_HorizontalHead[section];}return QAbstractTableModel::headerData(section, orientation, role);
}// 返回索引数据
QVariant TableModel::data(const QModelIndex index, int role) const {// 不存在则返回默认if (!index.isValid()) return QVariant();if (role Qt::DisplayRole || role Qt::EditRole) {switch (index.column()) {case COLUMN_HEAD_INDEX::No:return this-m_No[index.row()];break;case COLUMN_HEAD_INDEX::Reference:return this-m_Reference[index.row()];break;case COLUMN_HEAD_INDEX::X:return this-m_X[index.row()];break;case COLUMN_HEAD_INDEX::Y:return this-m_Y[index.row()];break;case COLUMN_HEAD_INDEX::Z:return this-m_Z[index.row()];break;case COLUMN_HEAD_INDEX::R:return this-m_R[index.row()];break;case COLUMN_HEAD_INDEX::Part:return this-m_Part[index.row()];break;case COLUMN_HEAD_INDEX::Feeder:return this-m_Feeder[index.row()];break;case COLUMN_HEAD_INDEX::Nozzle:return this-m_Nozzle[index.row()];break;case COLUMN_HEAD_INDEX::HD:return this-m_HD[index.row()];break;case COLUMN_HEAD_INDEX::CY:return this-m_CY[index.row()];break;case COLUMN_HEAD_INDEX::AR:return this-m_AR[index.row()];break;case COLUMN_HEAD_INDEX::BL:return this-m_BL[index.row()];default:return QVariant();break;}} else if (role Qt::CheckStateRole) {switch (index.column()) {case COLUMN_HEAD_INDEX::CS:return this-m_CS[index.row()] Qt::Checked ? Qt::Checked : Qt::Unchecked;break;case COLUMN_HEAD_INDEX::SK:return this-m_SK[index.row()] Qt::Checked ? Qt::Checked : Qt::Unchecked;break;case COLUMN_HEAD_INDEX::FID:return this-m_FID[index.row()] Qt::Checked ? Qt::Checked : Qt::Unchecked;break;default:return QVariant();break;}}return QVariant();
}// 返回模型索引
QModelIndex TableModel::index(int row, int column, const QModelIndex parent) const {// 行和列的合法性检查if (row 0 || row this-m_No.size() || column 0 || column COLUMN_HEAD_INDEX::COLUMN) {return QModelIndex();}switch (column) {case COLUMN_HEAD_INDEX::No:// 获取对应行和列单元格的数据//QString str this-m_No[row];// 新建一个索引并绑定指针数据返回return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Reference://QString str this-m_Reference[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::X://QString str this-m_X[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Y://QString str this-m_Y[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Z://QString str this-m_Z[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::R://QString str this-m_R[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Part://QString str this-m_Part[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Feeder://QString str this-m_Feeder[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::Nozzle://QString str this-m_Nozzle[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::HD://QString str this-m_HD[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::CS://QString str this-m_CS[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::CY://QString str this-m_CY[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::SK://QString str this-m_SK[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::AR://QString str this-m_AR[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::FID://QString str this-m_FID[row];return createIndex(row, column/*, str*/);break;case COLUMN_HEAD_INDEX::BL://QString str this-m_BL[row];return createIndex(row, column/*, str*/);break;default:return createIndex(row, column);break;}return createIndex(row, column);
}// 返回模型索引的编辑方式
Qt::ItemFlags TableModel::flags(const QModelIndex index) const {if (!index.isValid()) {// 返回用户可以与界面进行交互return Qt::ItemIsEnabled | Qt::ItemIsSelectable;}switch (index.column()) {case COLUMN_HEAD_INDEX::No:// 返回用户可以与界面进行交互return Qt::ItemIsEnabled | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Reference:// 返回用户可以进行编辑return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::X:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Y:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Z:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::R:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Part:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Feeder:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::Nozzle:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::HD:return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::CS:return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;break;case COLUMN_HEAD_INDEX::CY:return Qt::ItemIsEnabled | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::SK:return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;break;case COLUMN_HEAD_INDEX::AR:return Qt::ItemIsEnabled | Qt::ItemIsSelectable;break;case COLUMN_HEAD_INDEX::FID:return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;break;case COLUMN_HEAD_INDEX::BL:return Qt::ItemIsEnabled | Qt::ItemIsSelectable;default:return Qt::ItemIsEnabled | Qt::ItemIsSelectable;break;}return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}// 设置模型索引数据
bool TableModel::setData(const QModelIndex index, const QVariant value, int role) {if (index.isValid() role Qt::EditRole) {switch (index.column()) {case COLUMN_HEAD_INDEX::No:this-m_No[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Reference:this-m_Reference[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::X:this-m_X[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Y:this-m_Y[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Z:this-m_Z[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::R:this-m_R[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Part:this-m_Part[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Feeder:this-m_Feeder[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::Nozzle:this-m_Nozzle[index.row()] value.toString();break;case COLUMN_HEAD_INDEX::HD:this-m_HD[index.row()] value.toString();break;//case COLUMN_HEAD_INDEX::CS:// //this-m_CS[index.row()] value.toString();// this-m_CS[index.row()] (value.toInt() Qt::Checked ? Qt::Checked : Qt::Unchecked);// break;case COLUMN_HEAD_INDEX::CY:this-m_CY[index.row()] value.toString();break;/*case COLUMN_HEAD_INDEX::SK:this-m_SK[index.row()] value.toString();break;*/case COLUMN_HEAD_INDEX::AR:this-m_AR[index.row()] value.toString();break;/*case COLUMN_HEAD_INDEX::FID:this-m_FID[index.row()] value.toString();break;*/case COLUMN_HEAD_INDEX::BL:this-m_BL[index.row()] value.toString();default:break;}// 设置完成后发射信号告诉视图数据有修改emit dataChanged(index, index); // 参数是左上角和右下角的模型索引这里是相同的return true;} else if (index.isValid() role Qt::CheckStateRole) {switch (index.column()) {case COLUMN_HEAD_INDEX::CS:this-m_CS[index.row()] (value.toInt() Qt::Checked ? Qt::Checked : Qt::Unchecked);break;case COLUMN_HEAD_INDEX::SK:this-m_SK[index.row()] (value.toInt() Qt::Checked ? Qt::Checked : Qt::Unchecked);break;case COLUMN_HEAD_INDEX::FID:this-m_FID[index.row()] (value.toInt() Qt::Checked ? Qt::Checked : Qt::Unchecked);break;default:break;}// 设置完成后发射信号告诉视图数据有修改emit dataChanged(index, index); // 参数是左上角和右下角的模型索引这里是相同的return true;}return false;
}// 插入行 参数插入的位置插入的行数父项的模型索引
bool TableModel::insertRows(int row, int count, const QModelIndex parent) {// 如果插入零行则返回false表示插入失败if (count 0) return false;// 没有父类if (!parent.isValid()) {// 从row开始插入行直到row count - 1处beginInsertRows(QModelIndex(), row, row count - 1);// 有父类} else {// 从row开始插入行直到row count - 1处beginInsertRows(parent, row, row count - 1);}// 按照位置在链表对应位置进行插入数据for (int addCount 0; addCount count; addCount) {this-m_No.insert(row addCount, );this-m_Reference.insert(row addCount, );this-m_X.insert(row addCount, );this-m_Y.insert(row addCount, );this-m_Z.insert(row addCount, );this-m_R.insert(row addCount, );this-m_Part.insert(row addCount, );this-m_Feeder.insert(row addCount, );this-m_Nozzle.insert(row addCount, );this-m_HD.insert(row addCount, );this-m_CS.insert(row addCount, Qt::CheckState::Unchecked);this-m_CY.insert(row addCount, );this-m_SK.insert(row addCount, Qt::CheckState::Unchecked);this-m_AR.insert(row addCount, );this-m_FID.insert(row addCount, Qt::CheckState::Unchecked);this-m_BL.insert(row addCount, );}// 结束插入行endInsertRows();return true;
}// 删除行
bool TableModel::removeRows(int row, int count, const QModelIndex parent) {if (count 0) return false;if (!parent.isValid()) {beginRemoveRows(QModelIndex(), row, row count - 1);} else {beginInsertRows(parent, row, row count - 1);}// 按照位置在链表对应位置进行移除数据for (int removeCount 0; removeCount count; removeCount) {this-m_No.removeAt(row);this-m_Reference.removeAt(row);this-m_X.removeAt(row);this-m_Y.removeAt(row);this-m_Z.removeAt(row);this-m_R.removeAt(row);this-m_Part.removeAt(row);this-m_Feeder.removeAt(row);this-m_Nozzle.removeAt(row);this-m_HD.removeAt(row);this-m_CS.remove(row removeCount);this-m_CY.removeAt(row);this-m_SK.remove(row removeCount);this-m_AR.removeAt(row);this-m_FID.remove(row removeCount);this-m_BL.removeAt(row);}endRemoveRows();return true;
}HzcTableEdit.h
#pragma once#include QtWidgets/QWidget
#include ui_HzcTableEdit.h
#include TableModel.h
#include WidgetDelegate.h#include QMenuclass HzcTableEdit : public QWidget {Q_OBJECTpublic:HzcTableEdit(QWidget *parent Q_NULLPTR);private:void setInsertRowData(int _row);bool isSelectionRows();// 右键显示菜单事件void contextMenuEvent(QContextMenuEvent * event);private slots:void on_selectBtn_clicked();void on_cancelBtn_clicked();void on_insertBtn_clicked();void on_removeBtn_clicked();void onCheckBox();void onUnCheckBox();void onCheckAndUnCheckBox(Qt::CheckState State);private:Ui::HzcTableEditClass ui;TableModel *m_tableModel;// QComboBoxQMapint, WidgetDelegate * m_cBoxDelegateArray;// 列的初始默认数据QMapint, QString m_columnData;// No.列int m_no;// 存储查找显示的索引QModelIndexList m_showList;// 菜单QMenu *m_menu;};HzcTableEdit.cpp
#include HzcTableEdit.h#include QDebug
#include QMessageBoxHzcTableEdit::HzcTableEdit(QWidget *parent) : QWidget(parent) {ui.setupUi(this);this-m_no 1;// 单元格的宽度int headWidth[COLUMN_HEAD_INDEX::COLUMN] { 40, 100, 80, 80, 80, 80, 100, 120, 100, 40, 30, 30, 30, 30, 30, 30 };QStringList part, feederList, nozzleList, HDList;part ;feederList A;nozzleList A EMPTY CN020 CN030 CN040 CN065 CN140 CN220 CN400;HDList 1 2 3 4 5 6 7;// 行的初始数据this-m_columnData.insert(COLUMN_HEAD_INDEX::X, 0.000);this-m_columnData.insert(COLUMN_HEAD_INDEX::Y, 0.000);this-m_columnData.insert(COLUMN_HEAD_INDEX::Z, 0.000);this-m_columnData.insert(COLUMN_HEAD_INDEX::R, 0.000);this-m_columnData.insert(COLUMN_HEAD_INDEX::CY, 1);this-m_columnData.insert(COLUMN_HEAD_INDEX::AR, 1);this-m_columnData.insert(COLUMN_HEAD_INDEX::BL, 0);this-m_tableModel new TableModel;ui.tableView-setModel(this-m_tableModel);this-m_cBoxDelegateArray.insert(COLUMN_HEAD_INDEX::Part, new WidgetDelegate(part));this-m_cBoxDelegateArray.insert(COLUMN_HEAD_INDEX::Feeder, new WidgetDelegate(feederList));this-m_cBoxDelegateArray.insert(COLUMN_HEAD_INDEX::Nozzle, new WidgetDelegate(nozzleList));this-m_cBoxDelegateArray.insert(COLUMN_HEAD_INDEX::HD, new WidgetDelegate(HDList));// 添加委托ui.tableView-setItemDelegateForColumn(COLUMN_HEAD_INDEX::Part, this-m_cBoxDelegateArray.value(COLUMN_HEAD_INDEX::Part));ui.tableView-setItemDelegateForColumn(COLUMN_HEAD_INDEX::Feeder, this-m_cBoxDelegateArray.value(COLUMN_HEAD_INDEX::Feeder));ui.tableView-setItemDelegateForColumn(COLUMN_HEAD_INDEX::Nozzle, this-m_cBoxDelegateArray.value(COLUMN_HEAD_INDEX::Nozzle));ui.tableView-setItemDelegateForColumn(COLUMN_HEAD_INDEX::HD, this-m_cBoxDelegateArray.value(COLUMN_HEAD_INDEX::HD));// 设置水平头文本居中ui.tableView-horizontalHeader()-setDefaultAlignment(Qt::AlignHCenter);//设置隔行变色ui.tableView-setAlternatingRowColors(true);// 设置最后一列填满表格剩余空间ui.tableView-horizontalHeader()-setStretchLastSection(true);// 设置表格行高ui.tableView-verticalHeader()-setDefaultSectionSize(30);for (int i 0; i COLUMN_HEAD_INDEX::COLUMN; i) {// 设置表格列宽ui.tableView-setColumnWidth(i, headWidth[i]);}// 设置用户可以拖动行//ui.tableView-verticalHeader()-setSectionsMovable(true);// 设置固定行高ui.tableView-verticalHeader()-setSectionResizeMode(QHeaderView::Fixed);//ui.tableView-horizontalHeader()-setSectionResizeMode(QHeaderView::Fixed);// 设置行表头背景颜色样式为浅黄色ui.tableView-horizontalHeader()-setStyleSheet(QHeaderView::section{background:#ffff9b;});// 设置列表头背景颜色样式为浅蓝色ui.tableView-verticalHeader()-setStyleSheet(QHeaderView::section{background:#a7fffa;});// 设置左上角两个表头相交的区域的颜色样式为浅灰色ui.tableView-setStyleSheet(QTableCornerButton::section{background:#c2c2c2;});this-m_menu new QMenu(this);QMenu *childMenu new QMenu(填充原件);// 定义菜单子项QAction *addRowAction new QAction(插入行);QAction *removeRowAction new QAction(删除行);QAction *skipPointsAction new QAction(跳过点);QAction *cancleSkipPointsAction new QAction(取消跳过点);QAction *skipJointBoardAction new QAction(跳过拼版);QAction *separator this-m_menu-addSeparator(); // 返回一个分隔符this-m_menu-addAction(addRowAction);this-m_menu-addAction(removeRowAction);this-m_menu-addAction(skipPointsAction);this-m_menu-addAction(cancleSkipPointsAction);this-m_menu-addAction(separator);this-m_menu-addAction(skipJointBoardAction);this-m_menu-addMenu(childMenu);connect(addRowAction, SIGNAL(triggered()), this, SLOT(on_insertBtn_clicked()));connect(removeRowAction, SIGNAL(triggered()), this, SLOT(on_removeBtn_clicked()));connect(skipPointsAction, SIGNAL(triggered()), this, SLOT(onCheckBox()));connect(cancleSkipPointsAction, SIGNAL(triggered()), this, SLOT(onUnCheckBox()));
}void HzcTableEdit::on_selectBtn_clicked() {// 清空链表this-m_showList.clear();QString lineEdit ui.lineEdit-text();QString rowStr ;// 为空则显示所有行if (lineEdit.isEmpty()) {for (int row 0; row m_tableModel-rowCount(); row) {ui.tableView-showRow(row);} return;}// 遍历所有行for (int row 0; row m_tableModel-rowCount(); row) {// 获得Reference单元格的文本QModelIndex index m_tableModel-index(row, COLUMN_HEAD_INDEX::Reference);rowStr m_tableModel-data(index).toString();if (rowStr.isEmpty()) {// 隐藏当前行ui.tableView-hideRow(row);} else {// Reference列的文本是否与输入框中的文本相等if (lineEdit.contains(rowStr)) {ui.tableView-showRow(row);// 将显示的行索引存入链表中this-m_showList.append(index);} else {ui.tableView-hideRow(row);}}}
}void HzcTableEdit::on_cancelBtn_clicked() {ui.lineEdit-setText();// 显示所有行for (int row 0; row m_tableModel-rowCount(); row) {ui.tableView-showRow(row);}// 点击了取消按钮链表需要清空this-m_showList.clear();
}void HzcTableEdit::on_insertBtn_clicked() {if (!isSelectionRows()) {QMessageBox::information(this, 提示, 请选中一行);return;}// 获取所有选中的索引QModelIndexList indexs ui.tableView-selectionModel()-selectedIndexes();if (indexs.size() 0) {m_tableModel-insertRows(m_tableModel-rowCount(), 1);setInsertRowData(m_tableModel-rowCount() - 1);return;}// 获得最后一个索引的行int row indexs.last().row();m_tableModel-insertRows(row 1, 1);setInsertRowData(row 1);
}void HzcTableEdit::on_removeBtn_clicked() {if (!isSelectionRows()) {QMessageBox::information(this, 提示, 请选中一行);return;}// 移除用户查询后选中的行if (this-m_showList.size() ! 0) {// 从后往前移除for (int row m_showList.size() - 1; row 0; row--) {m_tableModel-removeRow(m_showList[row].row());}m_showList.clear();return;}// 获取所有选中列的行不重复QModelIndexList indexs ui.tableView-selectionModel()-selectedRows();if (indexs.size() 0) return;// 检测用户选择的项是否是连续的bool successionFlag true;for (int row 0; row indexs.size(); row) {if (row 1 indexs.size()) break;if (indexs[row].row() 1 ! indexs[row 1].row()) {successionFlag false;break;}}if (successionFlag) {m_tableModel-removeRows(indexs.first().row(), indexs.size());} else {for (int row indexs.size() - 1; row 0; row--) {m_tableModel-removeRow(indexs[row].row()); // 实际是调用removeRows(indexs[row].row(), 1),进行删除一行}}// 删除完后对No列进行排序this-m_no m_tableModel-rowCount();for (int row 0; row m_no; row) {QModelIndex index m_tableModel-index(row, 0);m_tableModel-setData(index, QString(%1).arg(row 1));}this-m_no 1;}// 为插入的行设置初始数据
void HzcTableEdit::setInsertRowData(int _row) {QString value ;QModelIndex index0 m_tableModel-index(_row, COLUMN_HEAD_INDEX::No);m_tableModel-setData(index0, QString(%1).arg(m_no));static int ref 1;QModelIndex index1 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Reference);m_tableModel-setData(index1, QString(%1).arg(ref));QModelIndex index2 m_tableModel-index(_row, COLUMN_HEAD_INDEX::X);m_tableModel-setData(index2, m_columnData.value(COLUMN_HEAD_INDEX::X));QModelIndex index3 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Y);m_tableModel-setData(index3, m_columnData.value(COLUMN_HEAD_INDEX::Y));QModelIndex index4 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Z);m_tableModel-setData(index4, m_columnData.value(COLUMN_HEAD_INDEX::Z));QModelIndex index5 m_tableModel-index(_row, COLUMN_HEAD_INDEX::R);m_tableModel-setData(index5, m_columnData.value(COLUMN_HEAD_INDEX::R));QModelIndex index6 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Part);value this-m_cBoxDelegateArray[COLUMN_HEAD_INDEX::Part]-getCurrentComboBoxData(0);m_tableModel-setData(index6, value);QModelIndex index7 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Feeder);value this-m_cBoxDelegateArray[COLUMN_HEAD_INDEX::Feeder]-getCurrentComboBoxData(1);m_tableModel-setData(index7, value);QModelIndex index8 m_tableModel-index(_row, COLUMN_HEAD_INDEX::Nozzle);value this-m_cBoxDelegateArray[COLUMN_HEAD_INDEX::Nozzle]-getCurrentComboBoxData(6);m_tableModel-setData(index8, value);QModelIndex index9 m_tableModel-index(_row, COLUMN_HEAD_INDEX::HD);value this-m_cBoxDelegateArray[COLUMN_HEAD_INDEX::HD]-getCurrentComboBoxData(1);m_tableModel-setData(index9, value);QModelIndex index10 m_tableModel-index(_row, COLUMN_HEAD_INDEX::CS);m_tableModel-setData(index10, Qt::CheckState::Unchecked);QModelIndex index11 m_tableModel-index(_row, COLUMN_HEAD_INDEX::CY);m_tableModel-setData(index11, m_columnData.value(COLUMN_HEAD_INDEX::CY));QModelIndex index12 m_tableModel-index(_row, COLUMN_HEAD_INDEX::SK);m_tableModel-setData(index12, Qt::CheckState::Unchecked);QModelIndex index13 m_tableModel-index(_row, COLUMN_HEAD_INDEX::AR);m_tableModel-setData(index13, m_columnData.value(COLUMN_HEAD_INDEX::AR));QModelIndex index14 m_tableModel-index(_row, COLUMN_HEAD_INDEX::FID);m_tableModel-setData(index14, Qt::CheckState::Unchecked);QModelIndex index15 m_tableModel-index(_row, COLUMN_HEAD_INDEX::BL);m_tableModel-setData(index15, m_columnData.value(COLUMN_HEAD_INDEX::BL));
}// 检查是否选中一整行
bool HzcTableEdit::isSelectionRows() {// 获取所有选中的索引QModelIndexList list ui.tableView-selectionModel()-selectedIndexes();// 存储被选中的所有行QVectorint selectedRows;// 获得所有选中单元格的行for each (QModelIndex index in list) {selectedRows.append(index.row());}// 进行排序std::sort(selectedRows.begin(), selectedRows.end());// 去除容器内重复元素auto it std::unique(selectedRows.begin(), selectedRows.end());selectedRows.erase(it, selectedRows.end());// 遍历所有行的单元格存在有一个单元格没有被选中则返回falsebool selectedFlag true;for (int row 0; row selectedRows.count(); row) {for (int column 0; column COLUMN_HEAD_INDEX::COLUMN; column) {QModelIndex index m_tableModel-index(selectedRows.at(row), column);// 检测该索引是否被选中if (ui.tableView-selectionModel()-isSelected(index) false) {selectedFlag false;break;}}// 为false直接返回结果if (selectedFlag false) return selectedFlag;}/* 此处为良好BUG 当用于没有选中任何单元格也会返回true是为了默认在行末尾连续插入行 */return selectedFlag;
}// 鼠标右键显示菜单事件
void HzcTableEdit::contextMenuEvent(QContextMenuEvent * event) {if (!isSelectionRows()) {return;}// 菜单出现的位置为当前鼠标的位置this-m_menu-exec(QCursor::pos());
}// 跳过点
void HzcTableEdit::onCheckBox() {onCheckAndUnCheckBox(Qt::CheckState::Checked);
}// 取消跳过点
void HzcTableEdit::onUnCheckBox() {onCheckAndUnCheckBox(Qt::CheckState::Unchecked);
}void HzcTableEdit::onCheckAndUnCheckBox(Qt::CheckState State) {// 获取所有选中的索引QModelIndexList list ui.tableView-selectionModel()-selectedIndexes();if (list.size() 0) return;// 存储被选中的所有行QVectorint selectedRows;// 获得所有选中单元格的行for each (QModelIndex index in list) {selectedRows.append(index.row());}// 进行排序std::sort(selectedRows.begin(), selectedRows.end());// 去除容器内重复元素auto it std::unique(selectedRows.begin(), selectedRows.end());selectedRows.erase(it, selectedRows.end());for each (int row in selectedRows) {// 获取到对应的索引QModelIndex index m_tableModel-index(row, COLUMN_HEAD_INDEX::SK);// 将设置索引数据为选中状态m_tableModel-setData(index, State, Qt::CheckStateRole);qDebug() m_tableModel-data(index, Qt::CheckStateRole).toBool();}
}如果想拷贝代码下来运行还得将文章开头链接委托里的代码也一并考下来方可运行。 总结 此篇博客也当做是代码记录吧。项目具体实现有兴趣的朋友得自己去看代码了代码量太多实在是不知道怎么写。 小项目结合了重写了委托QItemDelegate、模型QAbstractTableModel类还有QTableVIew的使用方法三者结合才有此小项目。如果你也有这方面的需求真的可以研究一下此小项目的代码。