在与用户交互时,有时候需要提供批处理操作,尤其是有大量数据,且对每条数据操作都非常相似的时候,就必须提供批量操作,以简化用户的操作。
在这里,实现了对QTableView或QTableWidget行操作的批量处理。
以下是批处理的效果示例:
在这里,我将view的vertical HeadView重写为了可勾选的复选框栏,并提供了一些操作接口以方便勾选操作。
代码:
#ifndef CBATCHVERTICALHEADERVIEW_H
#define CBATCHVERTICALHEADERVIEW_H
/*
* 这是为QTableView或者QTableWidget所写的一个批量操作控件。
*
* 它事实上就是View上的Vertical HeadView,只不错这里不再绘制行数,而是checkbox。
*
* 原理:在HeadView设置给View之后,通过HeadView返回的model,其实是View相关的Model,
* 因此,我们将是否勾选的信息写入 model的第一列中的CheckedRole中,默认CheckedRole 为 Qt::UserRole+1
* 如果和其他逻辑有冲突,可以修改CheckRole的实际值。然后重载paintSection,获取第一列的CheckRole的值,绘制
* 相关图像即可。
*
* 由于View会在model变化时自动去重新绘制HeadView,因此剩下的交给Model/View固有逻辑即可。
*
*/
#include <QHeaderView>
#include <QList>
#include <functional>
#define CheckedRole Qt::UserRole+1
class CBatchVerticalHeaderView : public QHeaderView
{
Q_OBJECT
public:
CBatchVerticalHeaderView(QWidget *parent = Q_NULLPTR);
void SetAllSelected();
void SetAllUnselected();
void SetSelected(int section,bool selected);
bool IsSelected(int section);
protected:
//重载paint函数,改为绘制checkbox
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
private slots:
void slotOnSectionClicked(int section);
};
#endif // CBATCHVERTICALHEADERVIEW_H
#include "BatchVerticalHeaderView.h"
#include <QDebug>
#include <QPainter>
#include <QStyle>
#include <QApplication>
static QRect CheckBoxRect(const QRect &rect)/*const*/
{
//绘制按钮所需要的参数
QStyleOptionButton checkBoxStyleOption;
//按照给定的风格参数 返回元素子区域
QRect checkBoxRect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption);
//返回QCheckBox坐标
QPoint checkBoxPoint(rect.x() + rect.width() / 2 - checkBoxRect.width() / 2,
rect.y() + rect.height() / 2 - checkBoxRect.height() / 2);
//返回QCheckBox几何形状
return QRect(checkBoxPoint, checkBoxRect.size());
}
CBatchVerticalHeaderView::CBatchVerticalHeaderView(QWidget *parent)
:QHeaderView(Qt::Vertical,parent)
{
this->setSectionsClickable(true);
this->setMinimumWidth(24);
connect(this,SIGNAL(sectionClicked(int)),this,SLOT(slotOnSectionClicked(int)));
}
void CBatchVerticalHeaderView::SetAllSelected()
{
QAbstractItemModel *model = this->model();
for(int section = 0;section < count();++section)
{
QModelIndex index = model->index(section,0);
model->setData(index,Qt::Checked,CheckedRole);
this->setVisible(false);
this->setVisible(true);
}
}
void CBatchVerticalHeaderView::SetAllUnselected()
{
QAbstractItemModel *model = this->model();
for(int section = 0;section < count();++section)
{
QModelIndex index = model->index(section,0);
model->setData(index,Qt::Unchecked,CheckedRole);
this->setVisible(false);
this->setVisible(true);
}
}
void CBatchVerticalHeaderView::SetSelected(int section, bool selected)
{
if(section < 0 || section >= this->count())
return;
QAbstractItemModel *model = this->model();
QModelIndex index = model->index(section,0);
Qt::CheckState oppsite = (selected) ? Qt::Checked : Qt::Unchecked;
model->setData(index,oppsite,CheckedRole);
this->setVisible(false);
this->setVisible(true);
}
bool CBatchVerticalHeaderView::IsSelected(int section)
{
if(section < 0 || section >= this->count())
return false;
QAbstractItemModel *model = this->model();
QModelIndex index = model->index(section,0);
Qt::CheckState checked = model->data(index,CheckedRole).value<Qt::CheckState>();
return (checked == Qt::Checked) ? true : false;
}
void CBatchVerticalHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
#if 1
QAbstractItemModel *model = this->model();
QModelIndex index = model->index(logicalIndex,0);
Qt::CheckState checkstate = model->data(index,CheckedRole).value<Qt::CheckState>();
bool checked = (checkstate == Qt::Checked) ? true : false;
QStyleOptionButton checkBoxStyleOption;
checkBoxStyleOption.state |= QStyle::State_Enabled;
checkBoxStyleOption.state |= checked? QStyle::State_On : QStyle::State_Off;
checkBoxStyleOption.rect = CheckBoxRect(rect);
QApplication::style()->drawControl(QStyle::CE_CheckBox,&checkBoxStyleOption,painter);
#else
painter->setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);
QAbstractItemModel *model = this->model();
QModelIndex index = model->index(logicalIndex,0);
Qt::CheckState checkstate = model->data(index,CheckedRole).value<Qt::CheckState>();
bool checked = (checkstate == Qt::Checked) ? true : false;
QString pic = checked ? "checked.png" : "unchecked.png";
painter->drawPixmap(rect,QPixmap(pic));
#endif
}
void CBatchVerticalHeaderView::slotOnSectionClicked(int section)
{
if(section < 0 || section >= this->count())
return;
QAbstractItemModel *model = this->model();
QModelIndex index = model->index(section,0);
Qt::CheckState checked = model->data(index,CheckedRole).value<Qt::CheckState>();
Qt::CheckState oppsite = (checked == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
model->setData(index,oppsite,CheckedRole);
}