You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复自定义QItemDelegate中drawCheck的复选框渲染异常?

QTableView自定义Boolean代理复选框渲染异常问题

我给QTableView的第一列添加了自定义代理BooleanItemDelegate,当前遇到复选框渲染异常:当所有可见复选框均勾选时渲染正常,但当两个及以上复选框未勾选时,复选框的白色勾选标记会闪烁,仿佛仅被部分重绘而非完整绘制。相关代码如下:

头文件 BooleanItemDelegate.h

#ifndef BOOLEANITEMDELEGATE_H
#define BOOLEANITEMDELEGATE_H

#include <QItemDelegate>
#include <QSqlTableModel>

class BooleanItemDelegate : public QItemDelegate
{

public:
    BooleanItemDelegate(QSqlTableModel* model, QObject* parent);
    ~BooleanItemDelegate();

public:
    void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex& index) const;
    bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);
};

#endif // BOOLEANITEMDELEGATE_H

源文件 BooleanItemDelegate.cpp

#include "BooleanItemDelegate.h"
#include <qcoreevent.h>

BooleanItemDelegate::BooleanItemDelegate(QSqlTableModel* model, QObject* parent)
    : QItemDelegate(parent)
{}


BooleanItemDelegate::~BooleanItemDelegate()
{}

void BooleanItemDelegate::paint(
    QPainter* painter,
    const QStyleOptionViewItem& option,
    const QModelIndex& index
) const
{
    drawBackground(painter, option, index);
    drawCheck(painter, option, option.rect, index.data().toBool() ? Qt::Checked : Qt::Unchecked);
    drawFocus(painter, option, option.rect);
}


bool BooleanItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
    if (event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick )
    {
        model->setData(index, !model->data(index).toBool());
        event->accept();
    }
    return QItemDelegate::editorEvent(event, model, option, index);
}

解决思路

  • 修复复选框绘制区域:当前直接把整个item的option.rect传给drawCheck,导致复选框占满整个单元格,重绘时容易出现区域重叠引发闪烁。应该通过样式获取复选框的正确绘制区域:
    void BooleanItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        painter->save();
        // 先绘制背景
        drawBackground(painter, option, index);
        // 获取复选框的正确位置
        QStyleOptionButton checkOpt;
        checkOpt.rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &option, nullptr);
        checkOpt.state = option.state | (index.data().toBool() ? QStyle::State_On : QStyle::State_Off);
        // 绘制复选框
        style()->drawControl(QStyle::CE_CheckBox, &checkOpt, painter);
        // 绘制焦点框
        drawFocus(painter, option, option.rect);
        painter->restore();
    }
    
  • 避免重复事件处理:在editorEvent中,处理完鼠标事件后仍调用父类的editorEvent,会导致同一事件被重复处理,触发多次数据变更和重绘,进而引发闪烁。处理完自定义逻辑后直接返回true即可:
    bool BooleanItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
    {
        if (event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick )
        {
            model->setData(index, !model->data(index).toBool());
            event->accept();
            return true; // 不再让父类处理该事件
        }
        return QItemDelegate::editorEvent(event, model, option, index);
    }
    
  • 确保重绘区域精准:如果上述修改后仍有闪烁,可在调用setData时明确指定数据角色,确保模型正确触发dataChanged信号,让视图精准重绘目标单元格:
    model->setData(index, !model->data(index).toBool(), Qt::EditRole);
    

内容的提问来源于stack exchange,提问作者Joseph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:40:55