Как 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 это немного сложно. Начиная с настроек с самым низким приоритетом:

  1. каждый QWidget имеет свойство palette, которое содержит набор цветов для различных состояний и элементов в виджете (в зависимости от стиля и платформы, работает или нет - обычно так и есть).
  2. Таблица стилей может переопределить палитру, вы можете установить эти цвета с помощью CSS в текстовом формате.
  3. Модель данных может предоставлять цвета, используя значение воспринимающей роли.

если вы предоставляете делегата, то вы несете ответственность за обработку цветов, если я найду какой-то шаблон для этого, я дам вам ссылку.

Другие вопросы по тегам