Qt没有内置的发光效果,只有一个QGraphicsDropShadowEffect类可以对整个控件产生阴影(可近似为外发光)效果。此处作者整理了如何用QPainter手工绘制形状的内发光或外发光效果。本文主要涉及到QPainter类中的图像混合模式技巧。下面允许我把Qt帮助中的内容复制过来供参考。
调用QPainter::setCompositionMode(...)方法可以对两个图像应用不同的混合方法。Qt默认的是Blend混合。混合过程中完全透明的像素作为“无”处理。请特别注意,CompositionMode是针对两个图像的混合,因此它的Destination和Source都应该是图像,尽量不要是QWidget。否则可能出现一些意外的效果。根据作者的理解应用混合模式的典型代码如下:
void main() { QPixmap background(w, h); /* Destination图片 */ background.fill(Qt::transparent); QPainter pq(&background); ... QPixmap pixmap(w, h); /* Source图片 */ pixmap.fill(Qt::transparent); QPainter pp(&pixmap); ... pq.setCompositionMode(QPainter::CompositionMode_DestinationOver); /* 设置混合模式 */ pq.drawPixmap(0, 0, pixmap); }
一、内发光效果
这里实现的是一个控件里绘制一个圆角矩形,然后对圆角矩形绘制内发光的效果。整体上是绿色背景,粉色的光影。测试环境是VS2017和Qt5.9。
头文件:
class MLighting : public QWidget { Q_OBJECT public: MLighting(QWidget* parent = 0); private: void paintEvent(QPaintEvent *event) override; };
CPP文件:
MLighting::MLighting(QWidget* parent) : QWidget(parent) { } void MLighting::paintEvent(QPaintEvent *event) { int w = width(); int h = height(); QPixmap background(w, h); background.fill(Qt::transparent); QPainter pq(&background); pq.setRenderHint(QPainter::Antialiasing); pq.setPen(Qt::NoPen); pq.setBrush(Qt::darkGreen); pq.drawRoundedRect(4, 4, w - 8, h - 8, 8, 8); QPixmap pixmap(w, h); pixmap.fill(Qt::transparent); QPainter pp(&pixmap); pp.setRenderHint(QPainter::Antialiasing); pp.setBrush(Qt::NoBrush); for (int p = 8; p >= 1; p -= 2) { pp.setPen(QPen(QColor(243, 163, 253, 64), p)); pp.drawRoundedRect(4, 4, w - 8, h - 8, 8, 8); } pq.setCompositionMode(QPainter::CompositionMode_SourceAtop); pq.drawPixmap(0, 0, pixmap); QPainter painter(this); painter.drawPixmap(0, 0, background); }
这里采用的混合模式是CompositionMode_SourceAtop,此模式将Source图像放在最上方并且超出Destination图像的范围外的部分会被裁剪掉。
二、外发光效果
整个代码与内发光差不多。效果图如下:
头文件:
class MLighting : public QWidget { Q_OBJECT public: MLighting(QWidget* parent = 0); private: void paintEvent(QPaintEvent *event) override; };
CPP文件:
MLighting::MLighting(QWidget* parent) : QWidget(parent) { } void MLighting::paintEvent(QPaintEvent *event) { int w = width(); int h = height(); QPixmap background(w, h); background.fill(Qt::transparent); QPainter pq(&background); pq.setRenderHint(QPainter::Antialiasing); pq.setPen(Qt::NoPen); pq.setBrush(Qt::darkGreen); pq.drawRoundedRect(4, 4, w - 8, h - 8, 8, 8); QPixmap pixmap(w, h); pixmap.fill(Qt::transparent); QPainter pp(&pixmap); pp.setRenderHint(QPainter::Antialiasing); pp.setBrush(Qt::NoBrush); for (int p = 8; p >= 1; p -= 2) { pp.setPen(QPen(QColor(243, 163, 253, 64), p)); pp.drawRoundedRect(4, 4, w - 8, h - 8, 8, 8); } pq.setCompositionMode(QPainter::CompositionMode_DestinationOver); pq.drawPixmap(0, 0, pixmap); QPainter painter(this); painter.drawPixmap(0, 0, background); }
这里采用的是CompositionMode_DestinationOver模式。此模式会将Destination图像放在上方,而Source图像放在下面混合。
标签:pixmap,pp,pq,Qt,background,或外,发光,QPainter From: https://www.cnblogs.com/mengxiangdu/p/17807104.html