Reputation: 12044
I have a QStyledItemDelegate for my QList widget:
class MappingDisplayWidgetDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
MappingDisplayWidgetDelegate(QObject *parent=NULL);
virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
virtual QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};
and it's paint method looks like:
void MappingDisplayWidgetDelegate::paint ( QPainter * painter,
const QStyleOptionViewItem & option,
const QModelIndex & index ) const
{
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
else if (option.state & QStyle::State_MouseOver)
painter->fillRect(option.rect, option.palette.midlight());
QFontMetrics fm(option.font);
QString filename = index.data(Qt::DisplayRole).toString();
QRect outline = option.rect;
int outmid = outline.center().y();
QRect fnBound = fm.boundingRect(filename);
int fnBoundMid = fnBound.center().y();
fnBound.moveLeft(outline.left());
fnBound.translate(0, outmid - fnBoundMid);
painter->drawText(fnBound, Qt::AlignVCenter | Qt::AlignLeft, filename);
}
Now this works, BUT the handling of the State_Selected and State_MouseOver doesn't produce the same results as the default lists. Here's a screen shot (I'm running on a Win7 system) of the code above on the left, and a standard QListWidget on the right. You can see that the QListWidget has nice gradients, while my items have only simple colors.
I want to paint my items to properly match the standard widgets, but I can't quite figure out how. I'm not seeing anything in the options that would give me the info I need.
Edited to add: Note that this is a somewhat toy example. The real code has a bunch of other stuff besides the one string, and has an appropriate (and working) sizeHint function. This is just a toy to demonstrate the problem.
Upvotes: 2
Views: 5453
Reputation: 280
I had the same question--I wanted to have a totally custom paint function, but take advantage of the built-in pretty selection painting. I've tried the below code, and so far I'm finding that it works great with no negative consequences:
void MassIndexItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const {
QStyledItemDelegate::paint(painter, option, QModelIndex());
//Above, note that rather than passing >index< to the inherited function, I pass a default, invalid index.
//Since my model's data() function returns an empty QVariant for invalid indexes,
//I get the default selection painting, but no other data is painted in any way.
//Below, I can do whatever painting I want and it will show up on top of the pretty selection paint
painter->drawEllipse(option.rect);
}
Upvotes: 1
Reputation: 12044
I'm detailing this as a usable solution, though it's not a great one.
If I don't put anything in the DisplayRole of the item, then I can call the underlying QStyledItemDelegate::paint routine and it will simply draw the proper background, thusly:
void MappingDisplayWidgetDelegate::paint ( QPainter * painter,
const QStyleOptionViewItem & option,
const QModelIndex & index ) const
{
QStyledItemDelegate::paint(painter, option, index);
QFontMetrics fm(option.font);
QString filename = index.data(Qt::UserRole).toString();
QRect outline = option.rect;
int outmid = outline.center().y();
QRect fnBound = fm.boundingRect(filename);
int fnBoundMid = fnBound.center().y();
fnBound.moveLeft(outline.left());
fnBound.translate(0, outmid - fnBoundMid);
painter->drawText(fnBound, Qt::AlignVCenter | Qt::AlignLeft,
filename);
}
I don't like this, and I'm going to be trying Dave's suggestion momentarily, but if one gets stuck, this does seem to work. On the down side it means you can't use the DisplayRole, so you can't use findItems in the QListWidget.
Upvotes: 0
Reputation: 17946
In the source code for drawing that element, the following call is made:
// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
I suspect you may want to do something similar to the following:
style().drawPrimitive(QStyle::PE_PanelItemViewItem, option, painter, NULL);
You may have to play around with the option
parameter to get the right rectangle target. Unfortunately, the computer I am using right now isn't set up to test any of this, so YMMV.
Upvotes: 2