1、Qt 渐变(二): 线性渐变与合成模式一起,实现倒影
依然是《 Java极富客户端》中的例子。
原始图像 | 原始图像+倒影 | 原始图像+倒影+合成模式 |
倒影是客户端中最流行的效果之一,而且还是最容易实现的效果之一(这一点令人惊奇) 。倒影的概念是通过模拟像光亮的塑料和擦亮的金属一样的可反射物质来提高用户界面的真实性。
要达到同样的效果,需要一个GradientPaint, 一个AlphaComposite和一些理论。创建一个 反射的过程需要三个步骤:
-
1) 像正常渲染一个物体一样渲染它。
-
2) 渲染这个物体上下颠倒的一个副本,就像在地上的一面镜子中看到的一样。
-
3) 模糊这个副本的一部分以使它淡出,随着它远离最初的物体。
实际上,需要用任意的物体而不是用颜色来绘制一个渐变。虽然直接执行这样的操作是不可能的,但是可以用一个透明遮盖物和适当的AlphaComposite来变相实现。
AlphaComposite可以用于混合源的像素值(在这个情况下是透明遮盖物)和目的地的像素值(物体的倒影)。这种想法是把这个物体与一个(从一个完全不透明的颜色变到一个完全透明的颜色的)渐变混合起来。因此,我们需要一个混合源和目的地的alpha值的合成规则。幸运的是,QPainter::CompositionMode_DestinationIn 恰好符合我们的需要。它的等式如下所示:
Ar = Ad * As
正如我们先前讨论的那样,表示生成的alpha值,Ar表示目标图像的alpha值, As表示源的alpha值。
设想把一个透明遮盖物和一个完全不透明的目标图像混合起来。按照这个规则,把一个来自透明遮盖物的不透明像素(As = 1)绘制到目标位置会导致一个完全不透明的 像素(Ar= l * 1 =1)。
作为对照,把一个来自透明遮盖物的透明像素(As =0)绘制到目标位置会导致一个完全透明的像素(Ar= l * 0=0)。因而,目标位置的每个像素都从遮盖物得到一 个alpha值并创建出期望的效果。由于alpha通道是相乘的,它也对半透明的目的地起作用。一旦知道使用哪个AlphaComposite,编写代码将变得非常容易:
- Qt 在实现倒影镜像时,更加方便,使用 :QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const &
ReflectionPanel.h
#ifndef REFLECTIONPANEL_H
#define REFLECTIONPANEL_H
#include <QWidget>
class ReflectionPanel : public QWidget
{
Q_OBJECT
public:
ReflectionPanel(QWidget *parent = nullptr);
~ReflectionPanel();
void paintEvent(QPaintEvent *event) override;
};
#endif // REFLECTIONPANEL_H
ReflectionPanel.cpp
#include "ReflectionPanel.h"
#include <QPainter>
#include <QLinearGradient>
ReflectionPanel::ReflectionPanel(QWidget *parent)
: QWidget(parent)
{
resize(380,380);
}
ReflectionPanel::~ReflectionPanel()
{
}
void ReflectionPanel::paintEvent(QPaintEvent *)
{
//可以设置widget为透明背景,但windows系统还要设置无边框才行,更麻烦
//背景画布
QImage res(width(),height(),QImage::Format_ARGB32_Premultiplied);
res.fill(0);
//画像
QImage img("Mirror Lake.jpg"); //320 * 185
//镜像倒影
QImage mirriored = img.mirrored(false,true);
QPainter painter;
//在背景画布上作画,
painter.begin(&res);
//画原图
painter.drawImage((width()-img.width()) / 2, 0, img);
//原图下画倒影图像
painter.drawImage((width()-img.width()) / 2, img.height(), mirriored);
//设置线性渐变,含alpha通道
QLinearGradient g(0, img.height(),0,height());
g.setColorAt(0,QColor(255,255,255,255));
g.setColorAt(0.5,QColor(255,255,255,0));
//设置图像合成模式
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
//绘制原图像
painter.fillRect(0,img.height(),width(),height(),g);
painter.end();
//绘制出背景图像
painter.begin(this);
painter.drawImage(0,0,res);
painter.end();
}