看了别人的内容,把原来的实现细节写了出来,并增加了许多说明性的语句和调试信息,讲解如何自定义一个抽象表格模型和使用,熟悉内部的实现流程。
代码如下,运行在centos qt环境下。
效果如下:
#ifndef TABLEMODEL_H
#define TABLEMODEL_H
#include <QString>
#include <QAbstractTableModel>
#include <QList>
struct FileRecord
{
bool bChecked;
QString strFilePath;
};
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit TableModel(QObject *parent = 0);
~TableModel();
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
int columnCount(const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
void updateData(QList<FileRecord> recordList);
signals:
public slots:
private:
QList<FileRecord> m_recordList;
};
#endif // TABLEMODEL_H
#include "tablemodel.h"
#include <QColor>
#include <QDebug>
#define CHECK_BOX_COLUMN 0
#define File_PATH_COLUMN 1
TableModel::TableModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
TableModel::~TableModel()
{
}
// 更新表格数据
void TableModel::updateData(QList<FileRecord> recordList)
{
m_recordList = recordList;
beginResetModel();//开始重置模型,相当于刷新功能,从模型中从新获取数据
endResetModel();//完成上面的过程,一般用在模型中开始的时候没有数据,然后需要重新刷新设置的模型,从中读取数据,在这个案例中,没有这两句话,是不能显示数据的。
}
// 行数
int TableModel::rowCount(const QModelIndex &parent) const
{
return m_recordList.count();
}
// 列数
int TableModel::columnCount(const QModelIndex &parent) const
{
return 2;
}
// 设置表格项数据,设置数据显示中的数据,一种是界面设置,一种是代码设置
bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)//value数据可以从界面获取。
{
if (!index.isValid())
{
return false;
qDebug()<<"index is valid";
}
int nColumn = index.column();
FileRecord record = m_recordList.at(index.row());
switch (role)
{
// case Qt::DisplayRole: //显示模式不能对数据进行更改
// {
// if (nColumn == File_PATH_COLUMN)
// {
// record.strFilePath = value.toString();
// qDebug()<<"value.toString():"<<value.toString();
// m_recordList.replace(index.row(), record);
// emit dataChanged(index, index);
// return true;
// }
// }
case Qt::EditRole: //编写模式,可以对数据进行更改
{
if (nColumn == File_PATH_COLUMN)
{
record.strFilePath = value.toString();
qDebug()<<"value.toString():"<<value.toString();
qDebug()<<"***************************";
m_recordList.replace(index.row(), record);
emit dataChanged(index, index);
return true;
}
}
case Qt::CheckStateRole: //根据状态修改数据库中的数据
{
if (nColumn == CHECK_BOX_COLUMN)
{
record.bChecked = (value.toInt() == Qt::Checked);
qDebug()<<"value.toInt():"<<value.toInt();
m_recordList.replace(index.row(), record);
emit dataChanged(index, index);
return true;
}
}
default:
return false;
}
return false;
}
// 表格项数据的获取:动态的从数据结构中获取数据,并将数据显示出来。
QVariant TableModel::data(const QModelIndex &index, int role) const
{
//i++;
if (!index.isValid())
{
qDebug()<<"index is not valid";
return QVariant();
}
int nRow = index.row();
int nColumn = index.column();
FileRecord record = m_recordList.at(nRow);
qDebug()<<record.bChecked;
qDebug()<<record.strFilePath;
//每个角色都是对应所有列的。
switch (role)
{
case Qt::TextColorRole:
{
qDebug()<<"Qt::TextColorRole"<<i;
return QColor(Qt::green);
}
case Qt::TextAlignmentRole:
{
qDebug()<<"Qt::TextAlignmentRole";
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
}
case Qt::DisplayRole://直接把数据显示出来。
{
qDebug()<<"Qt::DisplayRole";
if (nColumn == File_PATH_COLUMN)
return record.strFilePath;//根据记录中的数据显示在图表中。
return "";
}
case Qt::EditRole: //只有选中的时候且双击才会显示出来。
{
qDebug()<<"Qt::EditRole";
if (nColumn == File_PATH_COLUMN)
return record.strFilePath;
return "";
}
case Qt::CheckStateRole: //这一行语句在第一列显示方格
{
qDebug()<<"Qt::CheckStateRole";
if (nColumn == CHECK_BOX_COLUMN)
return record.bChecked ? Qt::Checked : Qt::Unchecked;
}
default:
{
qDebug()<<"default";
return QVariant();
}
}
return QVariant();
}
// 表头数据,表头数据没有从数据结构中获取,而是写死的。
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
switch (role)
{
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
case Qt::DisplayRole:
{
if (orientation == Qt::Horizontal)
{
if (section == CHECK_BOX_COLUMN)
return QStringLiteral("状态");
if (section == File_PATH_COLUMN)
return QStringLiteral("文件路径");
}
}
default:
return QVariant();
}
return QVariant();
}
// 表格可选中、可复选
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index);
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;//ItemIsEnabled,表明这一项可以使用,ItemIsSelectable 表明这一项可以选中。
// flags |= Qt::ItemIsUserCheckable|Qt::ItemIsEditable;
// Qt::ItemFlags tempFlag =Qt::ItemIsSelectable;
// return tempFlag;
if (index.column() == CHECK_BOX_COLUMN)//增加第一列的控制选项。
flags |= Qt::ItemIsUserCheckable|Qt::ItemIsEditable;
return flags;
}
#include "dialog.h"
#include <QApplication>
#include "tablemodel.h"
#include <QTableView>
#include <QHeaderView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Dialog w;
// w.show();
QTableView *pTableView = new QTableView;
TableModel *pModel = new TableModel;
// pModel->setHeaderData(1,Qt::Vertical,Qt::DisplayRole);
// 设置单行选中、最后一列拉伸、表头不高亮、无边框等
pTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
pTableView->horizontalHeader()->setStretchLastSection(true);
pTableView->horizontalHeader()->setHighlightSections(false);//当选中表中数据时,表头是否会高亮,显示已经选中状态。
pTableView->verticalHeader()->setVisible(true);
pTableView->setShowGrid(true); //是否显示网格线
//pTableView->setFrameShape(QFrame::NoFrame);
pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
pTableView->setModel(pModel);
// 加载数据、更新界面
QList<FileRecord> recordList;
for (int i = 0; i < 5; ++i)
{
FileRecord record;
record.bChecked = false;
record.strFilePath = QString("E:/Qt/image_%1.png").arg(i + 1);
recordList.append(record);
}
pModel->updateData(recordList);
pTableView->show();
return a.exec();
}