QAbstractTableModel 和委托的结合使用
来源:互联网 发布:张伯伦生涯场均数据 编辑:程序博客网 时间:2024/06/05 11:04
分析QAbstractTableModel 和委托的结合使用,自制一个复选框,并进行点击和数据的更新。
图片的展示效果图如下
#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;
// }
// }
case Qt::UserRole: //用户模式后,才能进行选中第一栏的数据
{
if (nColumn == CHECK_BOX_COLUMN)
{
record.bChecked = value.toBool();
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";
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;
// }
case Qt::UserRole:
{
if (nColumn == CHECK_BOX_COLUMN)
return record.bChecked;
}
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;
}
#ifndef CHECKBOXDELEGATE_H
#define CHECKBOXDELEGATE_H
#include <QStyledItemDelegate>
#include <QPainter>
#include <QStyleOptionViewItem>
#include <QModelIndex>
#include <QEvent>
#include <QMouseEvent>
#include <QCheckBox>
class CheckBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit CheckBoxDelegate(QObject *parent = 0);
~CheckBoxDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
public slots:
private:
int row;
};
#endif // CHECKBOXDELEGATE_H
#include "checkboxdelegate.h"
#include <QApplication>
#include <QDebug>
#include <QWidget>
#define CHECK_BOX_COLUMN 0
CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
row =0;
}
CheckBoxDelegate::~CheckBoxDelegate()
{
}
// 绘制复选框后面必须有const,没有const修饰,则不能显示自制矩形框,有const后,则内部不能修改数据,是一个只读的结构
void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
/*initialize option with the values using the index index. This method is useful for subclasses
when they need a QStyleOptionViewItem, but don't want to fill in all the information themselves.*/
if (option.state.testFlag(QStyle::State_HasFocus))
{
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
}
QStyledItemDelegate::paint(painter, viewOption, index);//必须放在这里,不能放在下面,
if (index.column() == CHECK_BOX_COLUMN)
{
bool data = index.model()->data(index, Qt::UserRole).toBool();//从模型中获取指定索引处的值
qDebug()<<"paint data:"<<data;
QStyleOptionButton checkBoxStyle;//设置自制按钮样式
checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;//一个是选中打勾状态,另一个则是没有选中打勾状态。
checkBoxStyle.state |= QStyle::State_Enabled;//使得自制的矩形框可以凸显出来
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect;//设置在第一栏显示矩形框,大小为第一列的宽度,没有这一句话,第一列将没有矩形框
//checkBoxStyle.rect = QRect(0,0,30,30);//这句话在第一栏设置一个矩形框,大小30,30,靠近第一栏的最左边显示出来,
//大小固定,不会变化。但是只能显示一行
qDebug()<<"row:"<<row;
QWidget widget;
//QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox);
//在widget上面绘制出矩形框
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &widget);
}
// row += 35;//由于paint是一个只读结构,不能更改
}
// 响应鼠标事件,更新数据。处理鼠标左键或者右键动作,以此来更新数据。
//对自制框进行操作时,才会触发editorEvent事件
bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
QRect decorationRect = option.rect;//用于判断鼠标是否落在矩形框内。
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
{
if (index.column() == CHECK_BOX_COLUMN)//由于视图显示设置为选择一行,如果这个没有判断,会发生选择第二列的时候,不断的刷新,点击第二列并不会对第一列的model数据进行更改。
//所以利用索引进行控制,在第一列。读取第一列的每个索引的数据,并进行重置第一列的每个数据。
{
bool data = model->data(index, Qt::UserRole).toBool();
qDebug()<<"editorEvent:****************"<<data;
model->setData(index, !data, Qt::UserRole);
}
// bool data = model->data(index, Qt::UserRole).toBool();
// qDebug()<<"editorEvent:****************"<<data;
// model->setData(index, !data, Qt::UserRole);
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
#include <QApplication>
#include "tablemodel.h"
#include <QTableView>
#include <QHeaderView>
#include <QSqlTableModel>
#include "checkboxdelegate.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView *pTableView = new QTableView;
TableModel *pModel = new TableModel;
// QSqlTableModel *pModel = new QSqlTableModel;
CheckBoxDelegate *pDelegate = new CheckBoxDelegate;
// 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);
pTableView->setItemDelegate(pDelegate);
// 加载数据、更新界面
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->resize(800,800);
pTableView->show();
return a.exec();
}
- QAbstractTableModel 和委托的结合使用
- QAbstractTableModel的使用
- 用户控件和委托的结合使用
- 委托和字典的结合使用
- QTableView与QAbstractTableModel的使用
- 异步委托调用和回调函数的结合使用
- 【C#】C#委托和字典的结合使用
- Qt中QAbstractTableModel、QItemDelegate的联合使用
- Qt:Quick:QAbstractTableModel的使用示例
- 委托和字典结合
- 委托的理解和使用
- 委托的声明和使用
- 委托和事件的使用
- 字典结合委托的Demo
- QTableView,Model/View的运用(1),QAbstractTableModel
- 委托的定义和使用入门
- 委托和匿名方法的使用
- 委托和接口的使用时机
- 分布式系统的事务处理
- Google广告AdMob的集成和使用
- android studio 2.2中进行ndk(c/c++)开发
- java加载spring配置文件
- 【转】mysql优化
- QAbstractTableModel 和委托的结合使用
- 2016 Unicode Conference拾遗(五)
- Web项目的WEB-INF目录使用说明以及重定向与转发
- 高精度加法
- 参数服务器代码解读(1)
- Spring事务理解-1
- 截屏工具类
- 统一设置根路径
- Java数据结构和算法-链表(5-迭代器)