具有 3 种可能值的图像

image with 3 possibility of value

我想个性化第 3 列以包含 QCheckBox 小部件。我希望使用三个图标自定义这些 QCheckBox 小部件:1.png(默认状态)| 2.png(选中状态)| 3.png(禁用状态)。所以我可以使用具有以下实现的自定义委托来做到这一点:

#include "mydelegate.h"
#include <QCheckBox>
#include <QPainter>
#include <QKeyEvent>
#include <QtDebug>
#include <QApplication>
#include <QStyleOptionViewItem>


MyDelegate::MyDelegate(QObject* parent) :
QStyledItemDelegate(parent)
{
// 1.png
_icon.addPixmap(QPixmap("1.png"), QIcon::Active, QIcon::On);
// 2.png
_icon.addPixmap(QPixmap("2.png"), QIcon::Selected, QIcon::On);
// 3.png
_icon.addPixmap(QPixmap("3.png"), QIcon::Disabled, QIcon::On);
}

void MyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& 
option, const QModelIndex& index) const
{
if (index.column() != 2)
    QStyledItemDelegate::paint(painter, option, index);
else
{
    bool value = index.model()->data(index, 
Qt::UserRole).toBool();
    QStyleOptionButton buttonVis;
    buttonVis.rect = option.rect;
    buttonVis.iconSize = QSize(50, 50);
    buttonVis.icon = _icon;
    buttonVis.features |= QStyleOptionButton::Flat;
    buttonVis.state |= value ? QStyle::State_Enabled : QStyle::State_None;
    QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonVis, painter);
}
}

bool MyDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, 
const QStyleOptionViewItem& option, const QModelIndex& index)
{
if (event->type() == QEvent::MouseButtonRelease)
{
    bool value = model->data(index, Qt::UserRole).toBool();
    model->setData(index, !value, Qt::UserRole);
}
return true;
}

它适用于 1.png 和 3.png 而不是 2.png 的问题。我希望它适用于三个图标

不需要实现paint(...) 或使用editorEvent(...) 方法,只需要通过启用图标的选项来覆盖initStyleOption(...) 方法。

在下面的示例中,项目 (2, 2) 被选中,项目 (4, 2) 被禁用,其他项目被启用但未被选中,显示 3 种类型的图标:

#include <QtWidgets>

class MyDelegate: public QStyledItemDelegate
{
public:
    MyDelegate(QObject *parent=nullptr):
        QStyledItemDelegate(parent)
    {
        m_icon.addPixmap(QPixmap("1.png"), QIcon::Active, QIcon::On);
        m_icon.addPixmap(QPixmap("2.png"), QIcon::Selected, QIcon::On);
        m_icon.addPixmap(QPixmap("3.png"), QIcon::Disabled, QIcon::On);
    }
    void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
        QStyledItemDelegate::initStyleOption(option, index);
        if (index.column() == 2){
            option->features |= QStyleOptionViewItem::HasDecoration;
            option->icon = m_icon;
            option->decorationSize = QSize(50, 50);
        }
    }
private:
    QIcon m_icon;
};


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTableWidget w(10, 4);
    MyDelegate *delegate = new MyDelegate(&w);
    w.setItemDelegate(delegate);
    QTableWidgetItem *item = new QTableWidgetItem;
    item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
    w.setItem(4, 2, item);
    w.show();
    return app.exec();
}

更新: OP 使用的术语不充分,因为它指的是小部件的状态(正常、选中、禁用),而是必须指示未选中的状态,部分查了查了。

#include <QtWidgets>

class MyDelegate: public QStyledItemDelegate
{
public:
    MyDelegate(QObject *parent=nullptr):
        QStyledItemDelegate(parent)
    {
        uncheckedIcon = QIcon("1.png");
        partiallyCheckedIcon = QIcon("2.png");
        checkedIcon = QIcon("3.png");
    }
    void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
        QStyledItemDelegate::initStyleOption(option, index);
        if (index.column() == 2){
            QIcon m_icon;
            QVariant value = index.data(Qt::UserRole);
            Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
            if(state == Qt::Unchecked)
                option->icon = uncheckedIcon;
            else if (state == Qt::PartiallyChecked)
                option->icon = partiallyCheckedIcon;
            else
                option->icon = checkedIcon;
            option->features |= QStyleOptionViewItem::HasDecoration;
            option->decorationSize = QSize(50, 50);
        }
    }
    bool editorEvent(QEvent* event, QAbstractItemModel* model,
                     const QStyleOptionViewItem& option, const QModelIndex& index) override
    {
        bool r = QStyledItemDelegate::editorEvent(event, model, option, index);
        if(index.column() != 2)
            return r;
        if ((event->type() == QEvent::MouseButtonRelease)
                || (event->type() == QEvent::MouseButtonDblClick)
                || (event->type() == QEvent::MouseButtonPress)) {
            if ((event->type() == QEvent::MouseButtonPress)
                    || (event->type() == QEvent::MouseButtonDblClick))
                return true;
            QVariant value = index.data(Qt::UserRole);
            Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
            state = static_cast<Qt::CheckState>((state + 1) % 3);
            return model->setData(index, state, Qt::UserRole);
        }
        return r;
    }
private:
    QIcon uncheckedIcon;
    QIcon partiallyCheckedIcon;
    QIcon checkedIcon;
};


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTableWidget w(10, 4);
    MyDelegate *delegate = new MyDelegate(&w);
    w.setItemDelegate(delegate);
    w.resize(640, 480);
    w.show();
    return app.exec();
}