QT QTableView添加CheckBox


需求:QTableView中指定列所有Item均为CheckBox项,要求CheckBox居中显示
显示效果如下:三种表现效果

 实现方式:
  1. 系统控件QCheckBox
  2. 自绘制CheckBox
  3. CheckBox的图片
实现代码:(原理:利用委托自绘的方式)
CheckBoxDelegate
#ifndef CHECKBOXDELETAGE_H
#define CHECKBOXDELETAGE_H

#include <QStyledItemDelegate>

class QPixmap;
class CheckBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    enum class CheckBoxPaintType : quint8
    {
        SysControl  = 0, // 系统控件
        OwnerDraw   = 1, // 自绘CheckBox
        DrawImage   = 2, // 绘制图片
    };

public:
    explicit CheckBoxDelegate(CheckBoxPaintType type = CheckBoxPaintType::SysControl, QWidget *parent = nullptr);
    ~CheckBoxDelegate();

    void initCheckBoxPixmaps(CheckBoxPaintType type);
    void initCheckBoxPixmapBySysControl(const QString& key, bool checked);
    void initCheckBoxPixmapByOwnerDraw(const QString& key, bool checked);
    void initCheckBoxPixmapByDrawImage(const QString& key, bool checked);

    // 虚函数
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;

signals:

private:
    QPixmap* mCheckedPix = nullptr;
    QPixmap* mUnCheckedPix = nullptr;
};

#endif // CHECKBOXDELETAGE_H
#include "checkboxdeletage.h"
#include <QCheckBox>
#include <QApplication>
#include <QMouseEvent>
#include <QPixmapCache>
#include <QPainter>

CheckBoxDelegate::CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType type, QWidget *parent)
    : QStyledItemDelegate(parent)
{
    initCheckBoxPixmaps(type);
}

CheckBoxDelegate::~CheckBoxDelegate()
{
    delete mCheckedPix;
    delete mUnCheckedPix;
}

void CheckBoxDelegate::initCheckBoxPixmaps(CheckBoxDelegate::CheckBoxPaintType type)
{
    switch (type)
    {
    case CheckBoxPaintType::SysControl:
        initCheckBoxPixmapBySysControl("checked", true);
        initCheckBoxPixmapBySysControl("unchecked", false);
        break;
    case CheckBoxPaintType::OwnerDraw:
        initCheckBoxPixmapByOwnerDraw("checked", true);
        initCheckBoxPixmapByOwnerDraw("unchecked", false);
        break;
    case CheckBoxPaintType::DrawImage:
        initCheckBoxPixmapByDrawImage("checked", true);
        initCheckBoxPixmapByDrawImage("unchecked", false);
        break;
    default:
        break;
    }
}

void CheckBoxDelegate::initCheckBoxPixmapBySysControl(const QString &key, bool checked)
{
    QPixmap* pix = new QPixmap(13,13);
    QPainter painter(pix);

    QStyleOptionToolButton style;
    style.iconSize = QSize(13, 13);
    style.state = checked ? QStyle::State_On : QStyle::State_Off;
    style.state |= QStyle::State_Enabled;
    style.rect = QRect(0,0, 13,13);
    QCheckBox box;
    QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &style, &painter, &box);

    if (checked)
        mCheckedPix = pix;
    else
        mUnCheckedPix = pix;
}

void CheckBoxDelegate::initCheckBoxPixmapByOwnerDraw(const QString &key, bool checked)
{
    QPixmap* pix = new QPixmap(13,13);
    QPainter painter(pix);
    painter.setPen(QColorConstants::Green);

    QRect rect(0,0,13,13);
    // 抗锯齿
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(QBrush(QColorConstants::White));
    painter.drawRect(rect);

    if (checked)
    {
        QPointF points[3] = {
            QPointF(rect.x() + rect.width() * 2 / 11, rect.y() + rect.height() * 6 / 11),
            QPointF(rect.x() + rect.width() * 4 / 11, rect.y() + rect.height() * 8 / 11),
            QPointF(rect.x() + rect.width() * 9 / 11, rect.y() + rect.height() * 3 / 11),
        };

        painter.setPen(QPen(QBrush(QColorConstants::Green),2));
        painter.drawPolyline(points, 3);
    }

    if (checked)
        mCheckedPix = pix;
    else
        mUnCheckedPix = pix;
    // 也可直接放入QPixmapCache中去,此处就简单处理更高效些
    //QPixmapCache::insert(key, pix);
}

void CheckBoxDelegate::initCheckBoxPixmapByDrawImage(const QString &key, bool checked)
{
    QPixmap* pix = new QPixmap(checked ? ":/image/checked.png" : ":/image/unchecked.png");

    if (checked)
        mCheckedPix = pix;
    else
        mUnCheckedPix = pix;
}


void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (viewOption.state.testFlag(QStyle::State_HasFocus))
        viewOption.state ^= QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, option, index);

    bool checked = index.data(Qt::UserRole).toBool();

    QPixmap* pix = checked? mCheckedPix : mUnCheckedPix;
    if (pix)
    {
        // 居中显示
        QRect rect = pix->rect();
        int offsetX = option.rect.width() / 2 - rect.width() / 2;
        int offsetY = option.rect.height() / 2 - rect.height() / 2;
        rect.translate(option.rect.x() + offsetX, option.rect.y() + offsetY);
        painter->drawPixmap(rect, *pix);
    }
}

bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
    {
        // 鼠标单双击切换选中状态
        QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
        if (option.rect.contains(mouseEvent->pos()))
        {
            model->setData(index, !model->data(index, Qt::UserRole).toBool(), Qt::UserRole);
        }
    }
    return QStyledItemDelegate::editorEvent(event, model, option, index);
}
使用:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTabWidget>
#include <QSplitter>
#include <QTableView>
#include <QStandardItemModel>
#include "checkboxdeletage.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QTabWidget* tabWidget = new QTabWidget(this);
    QSplitter* splitter = new QSplitter(Qt::Orientation::Horizontal, this);

    QTableView* tableView = new QTableView(this);

    QStandardItemModel* model = new QStandardItemModel(2,3,this);
    tableView->setModel(model);

    tableView->setItemDelegateForColumn(0, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::SysControl, this));
    tableView->setItemDelegateForColumn(1, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::OwnerDraw, this));
    tableView->setItemDelegateForColumn(2, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::DrawImage, this));
    // 不可编辑
    tableView->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
    // 整行选中
    tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    // 多行可选
    tableView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);

    splitter->addWidget(tableView);
    tabWidget->addTab(splitter, "CheckBox");

    setCentralWidget(tabWidget);
}

MainWindow::~MainWindow()
{
    delete ui;
}

QTableView如果实现指定项不可编辑状态方法:
  1. 重写Model的虚函数flags,指定index下的item的flags去除Qt::ItemIsEditable标志
  2. 重写DelegatecreateEditor,实现返回空的editor即可
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
QtQTableView添加复选框可以通过自定义一个QItemDelegate来实现。下面是一个简单的示例: 首先,我们定义一个继承自QItemDelegate的自定义委托类,名称为CheckBoxDelegate: ```cpp class CheckBoxDelegate : public QItemDelegate { public: CheckBoxDelegate(QObject* parent = nullptr) : QItemDelegate(parent) { } void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { if (index.column() == 0) { QStyleOptionButton checkBoxOption; checkBoxOption.rect = option.rect; checkBoxOption.state = index.data(Qt::CheckStateRole).toBool() ? QStyle::State_On : QStyle::State_Off; QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxOption, painter); } else { QItemDelegate::paint(painter, option, index); } } QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override { if (index.column() == 0) { QCheckBox* checkBox = new QCheckBox(parent); return checkBox; } else { return QItemDelegate::createEditor(parent, option, index); } } void setEditorData(QWidget* editor, const QModelIndex& index) const override { if (index.column() == 0) { bool checked = index.data(Qt::CheckStateRole).toBool(); QCheckBox* checkBox = static_cast<QCheckBox*>(editor); checkBox->setChecked(checked); } else { QItemDelegate::setEditorData(editor, index); } } void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override { if (index.column() == 0) { QCheckBox* checkBox = static_cast<QCheckBox*>(editor); model->setData(index, checkBox->isChecked(), Qt::CheckStateRole); } else { QItemDelegate::setModelData(editor, model, index); } } }; ``` 然后,在我们的QTableView中使用这个自定义委托类来实现复选框的功能: ```cpp QTableView* tableView = new QTableView; QStandardItemModel* model = new QStandardItemModel; // 设置表格大小 model->setRowCount(3); model->setColumnCount(2); // 设置表头 model->setHeaderData(0, Qt::Horizontal, "复选框列"); model->setHeaderData(1, Qt::Horizontal, "其他列"); // 设置复选框数据 model->setData(model->index(0, 0), Qt::Checked, Qt::CheckStateRole); model->setData(model->index(1, 0), Qt::Unchecked, Qt::CheckStateRole); model->setData(model->index(2, 0), Qt::Checked, Qt::CheckStateRole); // 设置委托 CheckBoxDelegate* checkBoxDelegate = new CheckBoxDelegate(tableView); tableView->setItemDelegateForColumn(0, checkBoxDelegate); // 设置数据模型 tableView->setModel(model); ``` 上述代码创建了一个QTableView和一个QStandardItemModel,并通过数据模型设置了3行2列的数据。使用自定义委托类CheckBoxDelegate将第一列的数据设置为复选框。然后将数据模型设置QTableView中。 最后,我们通过`tableView->setModel(model)`将数据模型设置QTableView中完成复选框的添加。 这样就可以在QTableView添加复选框了。记得在使用前先将相应的头文件导入:`#include <QCheckBox>`、`#include <QPainter>`、`#include <QStandardItemModel>`、`#include <QTableView>`、`#include <QItemDelegate>`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值