Как QListWidget устанавливает черный или белый выделенный текст?
Стандартный QListWidget рисует белый текст выбранной строки в Windows XP и черный в Windows 7/8. Где это взять черный или белый цвет?
Я создал пользовательский делегат для ListView и попытался нарисовать текст в выбранной строке, но палитра приложения возвращает те же цвета (HighlightedText, BrightText, WindowText, Text) на WinXP и 8, в то время как делегат по умолчанию каким-то образом рисует его черным или белым. Я просмотрел источник Qt и не смог найти, где он получает контрастный цвет. Сам стиль QListWidget возвращает одинаковый цвет ForegroundRole также на всех платформах.
Мне не хватает способа получить правильную палитру ОС в приложении Qt?
3 ответа
К сожалению, не все цвета читаются через QPalette. Специально для подклассов QAbstractItemView (представления списка, представления дерева…) стиль Windows извлекает цвета через WinAPI и использует их непосредственно для рисования.
Весь соответствующий код должен быть в qtbase/src/widgets/styles/qwindowsxpstyle.cpp и qtbase/src/widgets/styles/qwindowsvistastyle.cpp, найти "pGetThemeColor".
Как говорит Марек, для некоторых из этих цветов можно переопределить эти значения по умолчанию, но невозможно прочитать их через Qt API.
Благодарю.
В любом случае, оказалось, что делегат QListWidget/View на самом деле не рисует текст - он запрашивает стиль для рисования нативного элемента управления, и это рисует контрастный текст где-то глубоко в движке тем Qt. Если перо и кисть такие же, как в палитре по умолчанию, их цвета могут быть изменены на os-themed. Родной рисунок решил для меня цвет текста.
void customDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// ...
QStyleOptionViewItemV4 opt = option;
opt.state = opt.state & (~QStyle::State_HasFocus); // no dots
opt.displayAlignment = Qt::AlignVCenter | Qt::AlignLeft; // or right
opt.features = QStyleOptionViewItemV2::HasDisplay;
opt.text = displayText(textGoesThere, opt.locale); // <--
opt.rect = option.rect;
//...
if (multipartDrawing) {
if (drawingSomethingAtLeft)
opt.viewItemPosition = QStyleOptionViewItem::Beginning;
else if (somethingAtRight)
opt.viewItemPosition = QStyleOptionViewItem::End;
else
opt.viewItemPosition = QStyleOptionViewItem::Middle;
}
else opt.viewItemPosition = QStyleOptionViewItem::OnlyOne;
owner->style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
//...
}
В случае QListWidget
это немного сложно. Начиная с настроек с самым низким приоритетом:
- каждый
QWidget
имеет свойство palette, которое содержит набор цветов для различных состояний и элементов в виджете (в зависимости от стиля и платформы, работает или нет - обычно так и есть). - Таблица стилей может переопределить палитру, вы можете установить эти цвета с помощью CSS в текстовом формате.
- Модель данных может предоставлять цвета, используя значение воспринимающей роли.
если вы предоставляете делегата, то вы несете ответственность за обработку цветов, если я найду какой-то шаблон для этого, я дам вам ссылку.