在與使用者互動時,有時候需要提供批處理操作,尤其是有大量資料,且對每條資料操作都非常相似的時候,就必須提供批量操作,以簡化使用者的操作。
在這裡,實作了對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);
}