PDA

View Full Version : All QStyleOptionButton in listview sunken when clicking one of them



jiveaxe
30th March 2013, 18:00
HI, I have the following strange behaviour: I created a QListView whose elements are delegates. The delegate contains a button implemented this way:


void ItemDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
...
QStyleOptionButton button;
button.rect = buttonRect;
button.features |= QStyleOptionButton::Flat;
button.state = _state | QStyle::State_Enabled;
QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
...
}

bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if( event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease ) {
} else {
_state = QStyle::State_Raised;
return true;
}

...
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if( !buttonRect.contains( mouseEvent->pos()) ) {
_state = QStyle::State_Raised;
return true;
}

if( event->type() == QEvent::MouseButtonPress) {
_state = QStyle::State_Sunken;
} else if( event->type() == QEvent::MouseButtonRelease) {
_state = QStyle::State_Raised;
// call slot
}
}


It works fine except that the first time (after starting the application) I click any button, all buttons show the State_Sunken; all others clicks, after the first one, are normals: only the clicked button show the sunken/raised effect.

Do you have any explaination for this?

Very thanks.

ChrisW67
30th March 2013, 20:36
Where is buttonrect defined/coming from?

The items in the view are all drawn by the same, single delegate (i.e. the list view items are not delegates). If buttonrect is kept state then then painting will be confused.

jiveaxe
30th March 2013, 21:02
Here the code (the same for paint() and editorEvent()):



QRect buttonRect;
buttonRect.setX(option.rect.width() - buttonSize - margin);
buttonRect.setY(option.rect.y() + (option.rect.height()/2 - buttonSize/2));
buttonRect.setWidth(buttonSize);
buttonRect.setHeight(buttonSize);


I omitted it in first post because, I thought, not significant.

ChrisW67
31st March 2013, 04:53
And _state? If this is a member variable then that single _state is used when rendering any of the items the view needs to paint.

jiveaxe
31st March 2013, 10:02
_state is effectively a member variable:


QStyle::State _state;

but if this is the problem, why the behaviour happens only on very first click and not in next?

ChrisW67
1st April 2013, 01:46
Are you initialising _state to QStyle::State_Raised in the constructor ?

jiveaxe
1st April 2013, 09:24
This is my constructor:


ItemDelegate::ItemDelegate(QObject *parent) :
QAbstractItemDelegate(parent)
{
_state = QStyle::State_Enabled;
}

Thanks for your patience

jiveaxe
1st April 2013, 12:22
I solved changing approach; I'm not using anymore _state member but int _currRow to track clicked button; here it is a sample code:



ItemDelegate::ItemDelegate(QObject *parent) :
QAbstractItemDelegate(parent)
{
_currRow = -1;
}

void ItemDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if (!index.isValid())
return;

QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);

...

QStyleOptionButton button;
button.rect = buttonRect;
button.features |= QStyleOptionButton::Flat;

if(_currRow == index.row())
button.state = QStyle::State_Sunken | QStyle::State_Enabled;
else
button.state = QStyle::State_Raised | QStyle::State_Enabled;

QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
}

bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
Q_UNUSED(model)

if( event->type() != QEvent::MouseButtonPress &&
event->type() != QEvent::MouseButtonRelease ) {
return true;
}

if( event->type() == QEvent::MouseButtonPress)
_currRow = index.row();
else
_currRow = -1;

...

QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if( !buttonRect.contains( mouseEvent->pos()) ) {
return true;
}

if( event->type() == QEvent::MouseButtonRelease) {
// call slot
}

return true;
}


Thanks ChrisW67 for your time.