Как запретить Qt альфа-смешивать выделение над значками в QListView?

У меня есть приложение Qt, которое использует QTableView и QListView. В обоих виджетах я показываю некоторые значки.

Проблема в том, что когда пользователь выбирает одну из записей, Qt alpha смешивает выделение со значками, делая значки менее контрастными и немного отличающимися по цвету.

Я хочу, чтобы Qt сначала рисовал выделение, а затем рисовал значки сверху, чтобы они выглядели одинаково независимо от того, выбраны они или нет. Как я могу это сделать?

Обновление:

Вот как выглядит моя проблема:

Эффект с обычным значком

Его легче заметить по белой прямоугольной иконке:

Эффект со значком белого прямоугольника

Когда вы проверяете значение цвета с помощью графического редактора, вы видите, что значение цвета изменяется. Я хотел бы, чтобы Qt рисовал значок без этого наложения.

Стиль QListView здесь оформлен с использованием цветового градиента фона. Но у меня та же проблема с QTableView, который не имеет стиля.

Кстати, все иконки SVG.


person ahe    schedule 06.01.2017    source источник
comment
У меня тоже есть эта проблема. Вы можете увидеть это в Qt Designer без какой-либо таблицы стилей, пользовательских стилей или чего-либо еще - значок, загруженный в выбранное состояние QIcon, получает измененные цвета. Я попробовал модифицированный делегат столбца и поменял местами состояния значков, и это влияет только на выбранное состояние!   -  person Hamish Moffatt    schedule 22.10.2018


Ответы (1)


Рисование элементов ItemView обрабатывается делегатом. Вы можете установить настраиваемого делегата для столбца, строки или отдельных элементов. Реализация по умолчанию просто делегирует рисование стилю виджета:

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

    QStyleOptionViewItem opt = option;
    initStyleOption(&opt, index);

    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}

Вы можете найти фактический код, который рисует здесь. Кажется, что все стили, поставляемые с Qt5, в конечном итоге делегируют отрисовку элементов ItemView этому коду. Что интересно, рассматриваемый код на самом деле рисует значок поверх выделения, поэтому вы должны использовать какой-то пользовательский стиль. Вызов, который рисует выбор:

proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);

Этот вызов предшествует всем другим вызовам рисования.

В своем пользовательском делегате вы должны иметь возможность попросить стиль отрисовать все, кроме значка, изменив QStyleOptionViewItem opt (см. первый фрагмент кода). Затем вы можете нарисовать иконку вручную, так же, как это делает QCommonStyle.

person Joseph Artsimovich    schedule 15.01.2017