У меня есть QStyledItemDelegate для моего виджета QList:
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;
};
и это метод рисования выглядит так:
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);
}
Теперь это работает, НО обработка State_Selected и State_MouseOver не дает таких же результатов, как списки по умолчанию. Вот снимок экрана (я работаю в системе Win7) приведенного выше кода слева и стандартный QListWidget справа. Вы можете видеть, что QListWidget имеет хорошие градиенты, в то время как мои элементы имеют только простые цвета.
Я хочу нарисовать свои элементы, чтобы они соответствовали стандартным виджетам, но я не могу понять, как именно. Я не вижу в опциях ничего, что дало бы мне необходимую информацию.
Отредактировано, чтобы добавить:
Обратите внимание, что это несколько игрушечный пример. Реальный код имеет кучу других вещей, кроме одной строки, и имеет соответствующую (и работающую) функцию sizeHint. Это просто игрушка для демонстрации проблемы.
в исходный код для рисования этого элемента делается следующий вызов:
// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
Я подозреваю, что вы можете сделать что-то похожее на следующее:
style().drawPrimitive(QStyle::PE_PanelItemViewItem, option, painter, NULL);
Возможно, вам придется поиграть с option
параметр, чтобы получить правильную цель прямоугольника. К сожалению, компьютер, который я сейчас использую, не настроен для проверки всего этого, поэтому YMMV.
У меня был тот же вопрос — я хотел, чтобы у меня была полностью настраиваемая функция рисования, но я воспользовался встроенной симпатичной картиной. Я попробовал приведенный ниже код, и до сих пор я обнаружил, что он прекрасно работает без негативных последствий:
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);
}
Я описываю это как полезное решение, хотя оно не очень удачное.
Если я ничего не помещаю в DisplayRole элемента, то я могу вызвать базовую подпрограмму QStyledItemDelegate :: paint, и она просто нарисует правильный фон, таким образом:
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);
}
Мне это не нравится, и я собираюсь на мгновение попробовать предложение Дейва, но если кто-то застрянет, похоже, это сработает. С другой стороны это означает, что вы не можете использовать DisplayRole, поэтому вы не можете использовать findItems в QListWidget.