изображение с 3 возможностью значения - PullRequest
3 голосов
/ 18 июня 2019

Я хотел бы персонализировать 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. я хочу, чтобы это работало для трех значков

1 Ответ

1 голос
/ 18 июня 2019

Нет необходимости реализовывать методы paint (...) или использовать editorEvent (...), необходимо только переопределить метод initStyleOption (...), включив параметр значка.

В следующем примере выбран элемент (2, 2), элемент (4, 2) отключен, а другие элементы включены, но не выбраны, показывая значки трех типов:

#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();
}

enter image description here

Обновление: ОП использует неадекватную терминологию, поскольку относится к состоянию виджета (обычный, выбранный, отключенный), вместо этого он должен указывать состояния, не отмеченные, частично проверенные и проверенные.

#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();
}

enter image description here

...