乐趣区

关于qt:Qt-绘制-PEFrameFocusRect

在应用 Qt 开发图形界面的时候,咱们不免要对各种控件进行从新绘制。记录一下我绘制 PE_FrameFocusRect 的通过。

PE_FrameFocusRect

绘制 QListWidgetItem 的选中框须要用到 QStyle::drawPrimitive。并且须要创立一个 QStyleOptionFocusRect 对象,它蕴含一个成员变量 QColor backgroundColor。依据 Qt 文档我一开始认为批改这个背景色彩,就能够简略地批改 PE_FrameFocusRect 的背景色,但事实上并非如此。

QColor QStyleOptionFocusRect::backgroundColor
This variable holds the background color on which the focus rectangle is being drawn
The default value is an invalid color with the RGB value (0, 0, 0). An invalid color is a color that is not properly set up for the underlying window system.

起初我去翻了一下源码才发现,QStyle::drawPrimitive 在描述 PE_FrameFocusRect 的时候基本没有用到这个成员。用到的却是 QPalette::Highlight 所保留的色彩,而后对其作一些批改。

QColor highlight(const QPalette &pal) const {if (isMacSystemPalette(pal))
        return QColor(60, 140, 230);
    return pal.color(QPalette::Highlight);
}

QColor highlightedOutline(const QPalette &pal) const {QColor highlightedOutline = highlight(pal).darker(125);
    if (highlightedOutline.value() > 160)
        highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160);
    return highlightedOutline;
}

void QFusionStyle::drawPrimitive(
    PrimitiveElement elem,
    const QStyleOption *option,
    QPainter *painter, const QWidget *widget) const
{QColor highlightedOutline = d->highlightedOutline(option->palette);
    
    // .......
    case PE_FrameFocusRect:
        if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(option)) {
            //### check for d->alt_down
            if (!(fropt->state & State_KeyboardFocusChange))
                return;
            QRect rect = option->rect;
            painter->save();
            painter->setRenderHint(QPainter::Antialiasing, true);
            painter->translate(0.5, 0.5);
            QColor fillcolor = highlightedOutline;
            fillcolor.setAlpha(80);
            painter->setPen(fillcolor.darker(120));
            fillcolor.setAlpha(30);
            QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
            gradient.setColorAt(0, fillcolor.lighter(160));
            gradient.setColorAt(1, fillcolor);
            painter->setBrush(gradient);
            painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1);
            painter->restore();}
        break;
    //........
}

QStyledItemDelegate::paint

晓得 QStyle::drawPrimitive 是如何利用 PE_FrameFocusRect 绘制选中框之后,咱们就能够在代理中设置参数。

void CustomedDelegate::paint(
    QPainter * painter, 
    const QStyleOptionViewItem & option, 
    const QModelIndex & index) const
{
    //........

    if (opt.state & QStyle::State_HasFocus)
    {
        QStyleOptionFocusRect fr;
        fr.QStyleOption::operator=(option);
        fr.state |= QStyle::State_KeyboardFocusChange;
        fr.state |= QStyle::State_Item;

        /*
            设置 hightlight 色彩
        */
        QColor fillColor(Qt::white);
        fr.palette.setBrush(QPalette::Highlight, fillColor);

        const QWidget* widget = option.widget;
        QStyle* style = widget ? widget->style() : QApplication::style();
        style->drawPrimitive(QStyle::PE_FrameFocusRect, &fr, painter, widget);
    }

    //........
}

以上的形式是最合乎 Qt 格调,然而它并不让我感到称心。因为传进的 setBrushfillColor 的值将会被批改,例如透明度。

有时候,UI 设计师只会给咱们提供最终的色彩成果,如果咱们把这个色彩赋值给 fillColor 的话,进去的成果就会变得与预期不一样。所以我模拟了 QStyle::drawPrimitivePE_FrameFocusRect 实现。

void CustomerDelegate::DrawFocusRect(
    QPainter * painter, 
    QColor color, 
    const QStyleOptionViewItem & option) const
{painter->save();
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->translate(0.5, 0.5);
    QLinearGradient gradient(option.rect.topLeft(), option.rect.bottomLeft());
    gradient.setColorAt(0, color);
    gradient.setColorAt(1, color);
    painter->setBrush(gradient);

    painter->setPen(color);
    painter->drawRoundedRect(option.rect.adjusted(0, 0, -1, -1), 1, 1);

    painter->restore();}

void WorkingViewDelegate::paint(
    QPainter * painter, 
    const QStyleOptionViewItem & option, 
    const QModelIndex & index) const
{
    //........

    if (opt.state & QStyle::State_HasFocus)
        DrawFocusRect(painter, QColor("#71717B"), option);
    //........
}

painter->translate(0.5, 0.5) 这一行代码很重要,因为如果没了这行代码可能会导致刷新问题。

退出移动版