PDA

View Full Version : Problem with QCheckBox on QListWidget using QItemDelegate



saimel
7th October 2013, 01:31
Hi comunity,

I need a QListWidget with check boxes in it, I used the QItemDelegate class and I reimplemented the functions paint(), sizeHint() and drawCheck(), I did it because I want to change the aligment of the icon, text and check box indicator, after doing it the listWidget was painted as I want, but the problem appear when I select an item and press space bar to select it up, the check box of the item doesn't get checked, the one who do it is the check box of the next item, and if I click on a check box indicator then it doesn't change the state(checked, unchecked), however, if I select an item and after that I move the cursor out of the listWidget and press space bar then the check box of the selected item gets checked, I sopouse I skip some validation, connection or function's reimplementation, but this is my first time using QItemDelegate so I will appreciate any help.

Thanks very much.

Here is my code:

itemdelegate.h

#include <QItemDelegate>

class ItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit ItemDelegate(QObject *parent = 0);

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawCheck(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, Qt::CheckState state) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;

signals:

public slots:

};

itemdelegate.cpp


#include "itemdelegate.h"
#include <QPainter>
#include <QApplication>

ItemDelegate::ItemDelegate(QObject *parent) :
QItemDelegate(parent)
{
}

void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect r = option.rect;

if(option.state & QStyle::State_Selected)
painter->fillRect(r, QColor::fromRgb(176, 222, 241, 100));

bool checked = index.data(Qt::CheckStateRole).toBool();
QString text = index.data(Qt::DisplayRole).toString();
QIcon icon = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));

r.setHeight(r.height() - 20);
icon.paint(painter, r, Qt::AlignHCenter | Qt::AlignBottom);

QRect textRect = r;
textRect.setTop(r.bottom());
textRect.setHeight(19);
textRect.setWidth(r.width() - 20);
textRect.setX(r.x() + 20);
painter->setPen(QPen(Qt::black));
painter->drawText(textRect.left(), textRect.top(), textRect.width(), textRect.height(),
Qt::AlignBottom | Qt::TextWordWrap, text, &r);

QRect checkRect = textRect;
checkRect.setX(checkRect.x() - 20);
checkRect.setWidth(20);
checkRect.setY(checkRect.y() + 6);
this->drawCheck(painter, option, checkRect, (checked) ? Qt::Checked : Qt::Unchecked);

r = option.rect;
painter->setPen(QPen(Qt::gray));
painter->drawRect(option.rect);
}

void ItemDelegate::drawCheck(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, Qt::CheckState state) const
{
if(!rect.isValid())
return;

QStyleOptionViewItem opt(option);
opt.rect = rect;

if(state == Qt::Unchecked)
opt.state |= QStyle::State_Off;
else
opt.state |= QStyle::State_On;

QStyle *style = QApplication::style();
style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, painter);
}

QSize ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
return QSize(130, 145);
}

and here is where I populate the listWidget


for(int i = 0; i < photosList.count(); ++i) {
item = new QListWidgetItem();
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);

QImageReader reader(photosDir.absolutePath() + "/" + photosList.at(i));
QSize size = reader.size();
reader.setQuality(reader.quality() / 2);

reader.setScaledSize(size);

item->setData(Qt::DisplayRole, photosList.at(i));
item->setData(Qt::DecorationRole, QPixmap::fromImage(reader.read()));

ui->previewsList->addItem(item);
qApp->processEvents();
}