在应用 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 格调,然而它并不让我感到称心。因为传进的 setBrush
的 fillColor
的值将会被批改,例如透明度。
有时候,UI 设计师只会给咱们提供最终的色彩成果,如果咱们把这个色彩赋值给 fillColor
的话,进去的成果就会变得与预期不一样。所以我模拟了 QStyle::drawPrimitive
对 PE_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)
这一行代码很重要,因为如果没了这行代码可能会导致刷新问题。