QT中表格制作继承QAbstractTableModel与重新相关方法示例,这边文章主要是给自己做一个记录。
当然这个是存在问题的,就是在表格中添加的复选框在debug模式下是可以选择的,但是在release模式下是不可以被选择的,当时我也在博客中提了问题,所以选择了另一种方式来实现复选框。
在Qt的QAbstractItemModel中,CheckStateRole用于处理与复选框相关的功能。默认情况下,CheckStateRole仅在编辑模式下可用,而在非编辑模式下是只读的。
当你在Debug模式下运行时,Qt会提供更多的开发者工具和信息,允许你查看和修改模型的各个属性和角色。因此,在Debug模式下,你可以选择CheckStateRole并更改其状态。
然而,在Release模式下,Qt会进行优化以提高性能和减小生成的可执行文件的大小。为此,Qt可能不会提供完整的开发者工具和信息,并且某些功能和角色可能会被禁用或限制。这就是为什么在Release模式下,CheckStateRole不能被选择和修改的原因。
如果你需要在Release模式下也能够选择CheckStateRole并进行操作,你可以考虑修改你的代码或自定义模型来满足你的需求。例如,你可以通过实现自定义的代理(QStyledItemDelegate或QItemDelegate)来处理复选框的状态,并根据用户操作更新模型数据
需要重写的方法
// 返回行个数
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
// 返回列个数
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
// 返回头文本
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// 返回索引数据
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
// 返回模型索引
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
// 返回模型索引的编辑方式
Qt::ItemFlags flags(const QModelIndex& index) const override;
// 设置模型索引数据
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
// 插入行
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
// 删除行
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
完整代码
EditableTableModel.h
#pragma warning(disable:4819)
#ifndef EDITABLETABLEMODEL_H
#define EDITABLETABLEMODEL_H
#include <QObject>
#include <QAbstractTableModel>
#include <QCheckBox>
#include <QList>
#define COLUMN_NUM 10
enum COLUMN_HEAD_INDEX {
CheckBox = 0,
Id = 1,
Format=2,
Type=3,
SendMode = 4,
Length=5,
Data=6,
SendTimes=7,
Interval=8,
Count = 9,
CANType = 10,
BRS = 11
};
class EditableTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit EditableTableModel(QObject* parent, int column);
// 返回行个数
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
// 返回列个数
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
// 返回头文本
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// 返回索引数据
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
// 返回模型索引
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
// 返回模型索引的编辑方式
Qt::ItemFlags flags(const QModelIndex& index) const override;
// 设置模型索引数据
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
// 插入行
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
// 删除行
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
private:
QList<int> m_CheckBox;
QStringList m_Id;
QStringList m_Alias;
QStringList m_Format;
QStringList m_Type;
QStringList m_Length;
QStringList m_Data;
QStringList m_Frames;
QStringList m_SendTimes;
QStringList m_Interval;
QStringList m_IDRule;
QStringList m_DataRule;
QStringList m_Comment;
QStringList m_CANType;
QStringList m_BRS;
QStringList m_Count;
QStringList m_SendMode;
// 存储水平方向头数据
QStringList m_HorizontalHead;
int m_column;
};
#endif // EDITABLETABLEMODEL_H
EditableTableModel.cpp
#include "EditableTableModel.h"
#include <QDebug>
EditableTableModel::EditableTableModel(QObject* parent, int column)
: QAbstractTableModel(parent), m_column(column)
{
this->m_HorizontalHead.append(tr(" "));
this->m_HorizontalHead.append(tr("Id"));
this->m_HorizontalHead.append(tr("Format"));
this->m_HorizontalHead.append(tr("Type"));
this->m_HorizontalHead.append(tr("SendMode"));
this->m_HorizontalHead.append(tr("Length"));
this->m_HorizontalHead.append(tr("Data(HEX)"));
this->m_HorizontalHead.append(tr("Send Times"));
this->m_HorizontalHead.append(tr("Interval(ms)"));
this->m_HorizontalHead.append(tr("Count"));
if(column > COLUMN_NUM) {
this->m_HorizontalHead.append(tr("CANType"));
this->m_HorizontalHead.append(tr("BRS"));
}
}
int EditableTableModel::rowCount(const QModelIndex& parent) const
{
// 某一列的数据个数即是行数
return this->m_Id.size();
}
int EditableTableModel::columnCount(const QModelIndex& parent) const
{
return m_column;
}
QVariant EditableTableModel::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 EditableTableModel::data(const QModelIndex& index, int role) const
{
// 不存在则返回默认
if(!index.isValid()) {
return QVariant();
}
// 如果角色为显示和编辑模式
if(role == Qt::DisplayRole || role == Qt::EditRole) {
switch(index.column()) {
case Id:
return this->m_Id[index.row()];
break;
case Format:
return this->m_Format[index.row()];
break;
case Type:
return this->m_Type[index.row()];
break;
case Length:
return this->m_Length[index.row()];
break;
case Data:
return this->m_Data[index.row()];
break;
case SendTimes:
return this->m_SendTimes[index.row()];
break;
case Interval:
return this->m_Interval[index.row()];
break;
case Count:
return this->m_Count[index.row()];
break;
case CANType:
return this->m_CANType[index.row()];
break;
case BRS:
return this->m_BRS[index.row()];
break;
case SendMode:
return this->m_SendMode[index.row()];
break;
default:
break;
}
} else if(role == Qt::CheckStateRole) {
switch(index.column()) {
case CheckBox:
return this->m_CheckBox[index.row()];
break;
default:
break;
}
}
return QVariant();
}
QModelIndex EditableTableModel::index(int row, int column, const QModelIndex& parent) const
{
// 行和列的合法性检查
if(row < 0 || row >= this->m_Id.size() || column < 0 || column >= m_column) {
return QModelIndex();
}
QString str = "";
switch(column) {
case CheckBox:
str = this->m_CheckBox[row];
return createIndex(row, column, &str);
break;
case Id:
str= this->m_Id[row];
return createIndex(row, column, &str);
break;
case Format:
str= this->m_Format[row];
return createIndex(row, column, &str);
break;
case Type:
str= this->m_Type[row];
return createIndex(row, column, &str);
break;
case Length:
str= this->m_Length[row];
return createIndex(row, column, &str);
break;
case Data:
str= this->m_Data[row];
return createIndex(row, column, &str);
break;
case SendTimes:
str= this->m_SendTimes[row];
return createIndex(row, column, &str);
break;
case Interval:
str= this->m_Interval[row];
return createIndex(row, column, &str);
break;
case Count:
str= this->m_Count[row];
return createIndex(row, column, &str);
break;
case CANType:
str= this->m_CANType[row];
return createIndex(row, column, &str);
break;
case BRS:
str= this->m_BRS[row];
return createIndex(row, column, &str);
break;
case SendMode:
str= this->m_SendMode[row];
return createIndex(row, column, &str);
break;
default:
break;
}
return createIndex(row, column);
}
Qt::ItemFlags EditableTableModel::flags(const QModelIndex& index) const
{
if(!index.isValid()) {
// 返回用户可以与界面进行交互
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
// 返回用户可以进行编辑 ItemIsEnabled可以点击 ItemIsEditable可以编辑 ItemIsSelectable可以选中
switch(index.column()) {
case Id:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
break;
case Format:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case Type:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case Length:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case Data:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
break;
case SendTimes:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
break;
case Interval:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
break;
case CANType:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case BRS:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case Count:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
case CheckBox:
return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
// return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
break;
case SendMode:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
default:
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
}
}
bool EditableTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
qDebug()<<"setData====value"<<value<<"role"<<role;
if(index.isValid() && role == Qt::EditRole) {
switch(index.column()) {
case Id:
this->m_Id[index.row()]= value.toString();
break;
case Format:
this->m_Format[index.row()]= value.toString();
break;
case Type:
this->m_Type[index.row()]= value.toString();
break;
case Length:
this->m_Length[index.row()]= value.toString();
break;
case Data:
this->m_Data[index.row()]= value.toString();
break;
case SendTimes:
this->m_SendTimes[index.row()]= value.toString();
break;
case Interval:
this->m_Interval[index.row()]= value.toString();
break;
case CANType:
this->m_CANType[index.row()]= value.toString();
break;
case BRS:
this->m_BRS[index.row()]= value.toString();
break;
case Count:
this->m_Count[index.row()]= value.toString();
break;
case SendMode:
this->m_SendMode[index.row()]= value.toString();
break;
default:
break;
}
// 设置完成后发射信号告诉视图数据有修改
emit dataChanged(index, index);
return true;
} else if(index.isValid() && role == Qt::CheckStateRole) {
switch(index.column()) {
case CheckBox:
qDebug()<<"value.toString();"<<value.toString();
this->m_CheckBox[index.row()] = value.toInt();
break;
default:
break;
}
// 设置完成后发射信号告诉视图数据有修改
emit dataChanged(index, index);
return true;
}
return false;
}
bool EditableTableModel::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_CheckBox.insert(row + addCount, 0);
this->m_Id.insert(row + addCount, "");
this->m_Format.insert(row + addCount, "");
this->m_Type.insert(row + addCount, "");
this->m_SendMode.insert(row + addCount, "");
this->m_Length.insert(row + addCount, "");
this->m_Data.insert(row + addCount, "");
this->m_SendTimes.insert(row + addCount, "");
this->m_Interval.insert(row + addCount, "");
this->m_Count.insert(row + addCount, "");
if(m_column > COLUMN_NUM) {
this->m_CANType.insert(row + addCount, "");
this->m_BRS.insert(row + addCount, "");
}
}
// 结束插入行
endInsertRows();
return true;
}
bool EditableTableModel::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_CheckBox.removeAt(row);
this->m_Id.removeAt(row);
this->m_Format.removeAt(row);
this->m_Type.removeAt(row);
this->m_SendMode.removeAt(row);
this->m_Length.removeAt(row);
this->m_Data.removeAt(row);
this->m_SendTimes.removeAt(row);
this->m_Interval.removeAt(row);
this->m_Count.removeAt(row);
if(m_column > COLUMN_NUM) {
this->m_CANType.removeAt(row);
this->m_BRS.removeAt(row);
}
}
endRemoveRows();
return true;
}