PDA

View Full Version : How to apply TreeView look & feel to a delegate?



estecb
13th March 2012, 01:45
Hi! I'm trying to add some pixmap (many pixmap in the same column, a progress bar and probably more stuff in the future) to my TreeView, I found the best way to do it is to set a delegate.
It does works properly, but it looks ugly when I select the row. I fill the background by doing painter.fillRect(option.rect, self.palette.highlight()), but on Windows Vista/7 it does not show the modern "explorer" look like it should, it shows a blue background.

I've search everywhere without any luck.

This is a snippet of my code:


class ProgressBarDelegate(QStyledItemDelegate):
def __init__(self, parent):
QStyledItemDelegate.__init__(self, parent)
self.palette = parent.palette()

def paint(self, painter, option, index):
if not index.isValid():
return None
#painter.save()
#if option.state & QStyle.State_Selected: #paint background if selected.
#painter.fillRect(option.rect, painter.brush())
#painter.fillRect(option.rect, self.palette.highlight())
progress = index.data()
bar_option = QStyleOptionProgressBar()
bar_option.rect = option.rect
bar_option.rect.setHeight(option.rect.height() - 1)
bar_option.rect.setTop(option.rect.top() + 1)
bar_option.minimum = 0
bar_option.maximum = 100
bar_option.progress = int(progress)
bar_option.text = progress + '%'
bar_option.textVisible = True
bar_option.textAlignment = Qt.AlignCenter
QApplication.style().drawControl(QStyle.CE_Progres sBar, bar_option, painter)
#painter.restore()


This is the current result:

http://i.stack.imgur.com/TIJK1.jpg

This is what I want:

http://i.stack.imgur.com/7WtQx.jpg


related stackoverflow question > http://stackoverflow.com/questions/7860271/pyqt-qstyleditemdelegate-in-qtableview-on-windows-vista-7

Spitfire
14th March 2012, 09:52
Is that what you wanted?

7498



void ProgressBarDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if( index.column() == 1 )
{
if( option.state & QStyle::State_Selected )
{
painter->fillRect( option.rect, option.palette.highlight() );
}

int progress = index.data().toInt();

QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.rect.setTop( option.rect.top() + 1 );
progressBarOption.rect.setHeight( option.rect.height() - 2 );
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;
progressBarOption.textAlignment = Qt::AlignCenter;

QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}

estecb
14th March 2012, 12:05
If only... but no, that's what I got now. As I said, it looks *almost* ok, just because the highlight color is pretty much the same as the "explorer" box border.
Just try with a different delegate, try drawing a pixmap or just text.

This should illustrate what I mean:



void ProgressBarDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if( option.state & QStyle::State_Selected )
{
painter->fillRect( option.rect, option.palette.highlight() );
}
QStyledItemDelegate::paint(painter, option, index);
}

Spitfire
14th March 2012, 15:14
I'm not getting what you want.

Do you want the 'modern highlight' - as you call it - to be over your progress bar/pixmap/anything, under it or not there at all?
The two example images you shown are not obious either. None of them have the progress bar cell selected.

If you want the highlight to be over the cell
7501
then do that:


void ProgressBarDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
if( index.column() == 1 )
{
int progress = index.data().toInt();

QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.rect.setTop( option.rect.top() + 1 );
progressBarOption.rect.setHeight( option.rect.height() - 2 );
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;
progressBarOption.textAlignment = Qt::AlignCenter;

QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}

QStyledItemDelegate::paint(painter, option, index);
}

If you want to keep the highlight but in the background
7502
then do this:


void ProgressBarDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QStyledItemDelegate::paint(painter, option, index);

if( index.column() == 1 )
{
int progress = index.data().toInt();

QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.rect.setTop( option.rect.top() + 1 );
progressBarOption.rect.setHeight( option.rect.height() - 2 );
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;
progressBarOption.textAlignment = Qt::AlignCenter;

QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}
}

Note: in both cases there's no filling any rectangles.

If you want the cell not to be highlighted at all, then do what I've already showed just change the background color to white.

If you want something else - then I have no idea what you want :(

estecb
14th March 2012, 18:19
Sorry, yes, that's what I want (the "explorer" selection box over or under the progress bar). I wasn't able to see it clearly in your previous example.

The thing is, I'm not getting the same result. This is my code, which is the same that yours but written in pySide (python):



class ProgressBarDelegate(QStyledItemDelegate):
def __init__(self, parent):
QStyledItemDelegate.__init__(self, parent=parent)

def paint(self, painter, option, index):

QStyledItemDelegate.paint(self, painter, option, index)

progress = index.data()
bar_option = QStyleOptionProgressBarV2()
bar_option.rect = option.rect
bar_option.rect.setHeight(option.rect.height() - 4)
bar_option.rect.setTop(option.rect.top() + 1)
bar_option.minimum = 0
bar_option.maximum = 100
bar_option.progress = int(progress)
bar_option.text = progress + '%'
bar_option.textVisible = True
bar_option.textAlignment = Qt.AlignCenter
QApplication.style().drawControl(QStyle.CE_Progres sBar, bar_option, painter)




class MyTreeView(QTreeView):
def __init__(self, parent=None):
QTreeView.__init__(self, parent)

self.items = [["something", "1", "11", "t5est", "t3est"], ]

headers = ['a', 'b', 'c', 'd', 'e']

#QAbstractItemModel
self._model = SimpleListModel(headers, self.items)
self.setModel(self._model)

self.pb_delegate = ProgressBarDelegate(self)
self.setItemDelegateForColumn(2, self.pb_delegate)



This is the result:
7503

Spitfire
15th March 2012, 12:01
I'm afraid I can't help you, I have no idea about python :(

But if you're not drawing the blue background, then style is doint it.
Try setting Window/Base/Button palette color to transparent on bar_option, maybe it will help - but that's only thing that comes to my mind.

Good luck.