1. Qt 图像合成模式(二): SourceIn_Demo
这个例子中的思路和图片素材都是采用《Java 极富客户端》的例子。Qt普及性的资料实在是不够,只有掌握了其他部分知识的学习才能用好Qt,对于C++来说这无可厚非,但是对于集成式的Qt框架,解决方案都已经固定了,相关的资料应该可以更加的细致。相对来说 Java中的基础性的知识还是比较多的,知识由浅入深,有原理有代码有资源,比较容易学习,Java的官网文档和教程做得还真是好。Qt的给出的教程就是一个大纲,里面涉及的知识及其原理只提到了相应的名词。书归正传,还是来看看本次的主题吧。
Srcln是一个有用的的合成。无论什么时候想要替换一个现有的图像的内容时,都可以使用它。下图演示了一个在屏幕上描绘一个简单的盾牌,并用渐变的蓝色 填充它的应用程序。
如果想要绘制一个相似的盾牌,但是在内部用一个图片而不是用渐变的颜色,那将会怎 样?通过在图形区域上设置Srcln透明合成可以容易地做到这一点:
![]() | ![]() | ![]() |
按照Srcln规则,只显示 源图像 位于目标图像内部的那部分。
可以使用这个技术为图片创建画框、剪切图画或图像,甚至还可以生成阴影。如果在原图 的上方填充一个黑色的矩形,就会获得一个阴影。在这个阴影的偏移位置和顶部再次绘制这个原图,将得到想要的效果。

Widget.h
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
QImage *picture;
QImage *landscape;
QCheckBox *shadow;
};
Widget.cpp
#include "Widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(350,250);
picture = new QImage("picture.png");
landscape = new QImage("landscape.jpg");
shadow = new QCheckBox("draw shadow",this);
shadow->move(10,height()-30);
//QWiget 默认没有布局管理器
qDebug() << layout();
// 事件关联
connect(shadow,&QCheckBox::stateChanged,[&](){
update();
});
}
Widget::~Widget()
{
delete picture;
delete landscape;
}
void Widget::resizeEvent(QResizeEvent */*event*/)
{
//绝对定位,需要刷新位置
shadow->move(10,height()-30);
}
void Widget::paintEvent(QPaintEvent */*event*/)
{
QPainter painter;
QImage *shadowImg=0;
QImage res(width(),height(),QImage::Format_ARGB32_Premultiplied);
//填空image数据
res.fill(0);
int x = (width() - picture->width() )/2;
int y = (height() - picture->height() )/2;
//-----绘制阴影画布
if(shadow->isChecked()){
shadowImg = new QImage(width(),height(),QImage::Format_ARGB32_Premultiplied);
//填空image数据
shadowImg->fill(0);
painter.begin(shadowImg);
painter.drawImage( x+4,y+8, *picture);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.setBrush(Qt::black);
//设置透明度,有点单独的alpha的意思。
painter.setOpacity(0.75);
painter.drawRect(0,0,width(),height());
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.drawImage( x,y, *picture);
painter.end();
}
// QWidget本身格式不是QImage::Format_ARGB32_Premultiplied
// 所以使用QImage当做一层画布
//-----绘制背景画布
painter.begin(&res);
painter.drawImage( x,y, *picture);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.drawImage((width() - landscape->width() )/2,(height() - landscape->height() )/2,*landscape);
painter.end();
//-----绘制到控件上
painter.begin(this);
if(shadowImg) {
painter.drawImage( 0,0,*shadowImg);
delete shadowImg;
}
painter.drawImage( 0,0,res);
painter.end();
}