天天看點

為QTableView添加批量處理界面操作

在與使用者互動時,有時候需要提供批處理操作,尤其是有大量資料,且對每條資料操作都非常相似的時候,就必須提供批量操作,以簡化使用者的操作。

在這裡,實作了對QTableView或QTableWidget行操作的批量處理。

以下是批處理的效果示例:

為QTableView添加批量處理界面操作

在這裡,我将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);
}
           

繼續閱讀