Qt图形特效:QGraphicsEffect

一、描述

1、QGraphicsEffect类是所有图形效果的基类。

2、效果通过挂接到渲染管道并在(例如QGraphicsPixmapItem、QWidget)和目标设备(例如QGraphicsView的视口)之间进行操作来更改元素的外观。 

Qt提供以下图形效果:

  • QGraphicsBlurEffect:模糊
  • QGraphicsDropShadowEffect:阴影
  • QGraphicsColorizeEffect:颜色
  • QGraphicsOpacityEffect:透明度

3、若要创建自定义效果,请创建QGraphicsEffect的子类(或任何其他现有的效果),然后重新实现虚函数draw()。每当需要重绘效果时,都会调用此函数。在draw()函数中,可以调用sourcePixmap()来获取图形效果源的像素图,然后可以对其进行处理。

4、如果效果改变,请使用update()重绘。如果自定义效果更改了源的边界矩形,例如径向发光效果可能需要应用额外的边距,则可以重新实现虚拟的boundingRectFor()函数,并在此矩形发生变化时调用updateBoundingRect()来通知框架。调用sourceChanged()函数以通知效果该源已以某种方式更改。

二、类型成员

1、QGraphicsEffect::ChangeFlag,该枚举描述了QGraphicsEffectSource中发生的变化。

  • SourceAttached:图形特效已安装在源上。
  • SourceDetached:图形特效已从源上卸载。
  • SourceBoundingRectChanged:源的边界矩形已更改。
  • SourceInvalidated:源的外观已更改。

2、QGraphicsEffect::PixmapPadMode,该枚举描述了应如何填充从sourcePixmap()返回的像素图。

  • NoPad:像素图不应接收任何其他填充。
  • PadToTransparentBorder:应填充像素图,以确保其具有完全透明的边框。
  • PadToEffectiveBoundingRect:应填充像素图以匹配图形特效的有效边界矩形。

三、属性

1、enabled : bool

此属性保存是否启用效果。如果禁用了效果,则将正常渲染源,而不会受到效果的干扰。 如果启用了效果,则将在应用效果的情况下渲染源。默认情况下启用此属性。使用此属性,可以在慢速平台上禁用某些效果,以确保用户界面具有响应性。

四、成员函数

1、void update()

图形特效的重绘。 需要重绘效果时调用此函数。 此功能不会触发源的重绘。

2、QRectF boundingRect()

返回此图形特效的有效边界矩形,即源在设备坐标中的边界矩形。

3、[virtual] QRectF boundingRectFor(const QRectF &rect)

参数是目标设备坐标中的矩形,返回此图形特效的有效边界矩形。在编写自定义效果时,每当更改任何可能导致此函数返回不同值的参数时,都必须调用updateBondingRect()。

4、void draw(QPainter *painter)

这个纯虚函数绘制效果,并在需要绘制源代码时调用。在QGraphicsEffect子类中重新实现此函数,以使用painter提供效果的绘图实现。此函数不应由用户显式调用。

5、void drawSource(QPainter *painter)

使用给定的QPainter直接绘制源。此函数只能从QGraphicsEffect::draw()调用。

6、QRectF sourceBoundingRect(Qt::CoordinateSystem system = Qt::LogicalCoordinates)

返回映射到给定系统的源的边界矩形。在draw()之外以Qt::DeviceCoordinates调用此函数将产生未定义的结果,因为没有可用的设备上下文。

Qt::CoordinateSystem:该枚举指定坐标系。

  • Qt::DeviceCoordinates:坐标相对于对象绘画设备的左上角。
  • Qt::LogicalCoordinates:坐标相对于对象的左上角。

7、void sourceChanged(QGraphicsEffect::ChangeFlags flags)

通知图形特效源已更改。如果图形特效应用了任何高速缓存,则必须清除此高速缓存以反映源的新外观。

8、bool sourceIsPixmap()

如果源实际上是一个像素图(例如QGraphicsPixmapItem),则返回true。此功能对于优化目的很有用。 例如,如果此函数返回true,则在设备坐标中绘制源来避免像素图缩放毫无意义-无论如何,源像素图都会缩放。

9、QPixmap sourcePixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = nullptr, QGraphicsEffect::PixmapPadMode mode = PadToEffectiveBoundingRect)

返回其中绘制了源的像素图。系统指定要用于源的坐标系。可选的offset参数返回应使用当前绘制器在其上绘制像素图的偏移量。要控制如何填充像素图,请使用mode参数。

10、void QGraphicsEffect::updateBoundingRect()

当效果的边界矩形已更改时,此函数会通知效果框架。作为自定义效果作者,只要更改任何会使虚boundingRectFor()函数返回不同值的参数,就必须调用此函数。如果需要,此函数将调用update()。

五、一个自定义发光图形特效的实例

代码来自:GlowEffect——发光效果的QGraphicsEffect,做了一些修改。

#ifndef GLOWEFFECT_H
#define GLOWEFFECT_H

#include <QGraphicsEffect>

//声明将使用qt内部的模糊图像函数
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);

class GlowEffect : public QGraphicsEffect
{
    Q_OBJECT
public:
    explicit GlowEffect(QObject *parent = nullptr);

private:
    int radius;
    QColor color;//发光颜色

protected:
    void draw(QPainter *painter)override;
    void sourceChanged(ChangeFlags flags)override;
    QRectF boundingRectFor(const QRectF &sourceRect) const override;
};

#endif // GLOWEFFECT_H
#include "gloweffect.h"
#include <qpainter.h>
#include <QPixmap>
#include <QDebug>

GlowEffect::GlowEffect(QObject *parent) :
    QGraphicsEffect(parent), radius(0), color(255, 255, 255, 255)
{
    radius = 15;
    color = Qt::red;
}

QRectF GlowEffect::boundingRectFor(const QRectF &sourceRect) const
{
    QRectF tmp(sourceRect);
    tmp.setBottomRight(tmp.bottomRight() + QPointF(radius * 2, radius * 2));
    return tmp;
}

void GlowEffect::sourceChanged(ChangeFlags flags)
{
    updateBoundingRect();
    update();
}

void GlowEffect::draw(QPainter *painter)
{
    if (radius == 0)
    {
        drawSource(painter);
        return;
    }
    QPixmap source = sourcePixmap();

    QImage sourceBlured(source.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
    sourceBlured.fill(Qt::transparent);

    QPainter tmpPainter;
    tmpPainter.begin(&sourceBlured);
    tmpPainter.drawPixmap(radius, radius, source);
    tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    tmpPainter.fillRect(sourceBlured.rect(), color);
    tmpPainter.end();

    qt_blurImage(sourceBlured, radius, true);
    sourceBlured.save(QString("xx%1.png").arg(i));
    ++i;

    for (int i = 0;i < 6;++i)
    {
        painter->drawImage(0, 0, sourceBlured);
    }

    painter->drawPixmap(radius, radius, source);
}

ui文件:

绘制代码分析

当绘制半径为0时,只绘制源,即不绘制图形特效

    if (radius == 0)
    {
        drawSource(painter);
        return;
    }

获取源对象的像素图,保存此像素图查看如下:

    QPixmap source = sourcePixmap();

 注意尺寸,可见源图像的尺寸由boundingRectFor()函数确定:

QRectF GlowEffect::boundingRectFor(const QRectF &sourceRect) const
{
    QRectF tmp(sourceRect);
    tmp.setBottomRight(tmp.bottomRight() + QPointF(radius * 2, radius * 2));
    return tmp;
}

  创建一个比源对象的像素图宽高都大radius * 2的图像,填充透明色:

    QImage sourceBlured(source.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
    sourceBlured.fill(Qt::transparent);

  在此图上绘制源对象像素图:

    QPainter tmpPainter;
    tmpPainter.begin(&sourceBlured);
    tmpPainter.drawPixmap(radius, radius, source);
    tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    tmpPainter.fillRect(sourceBlured.rect(), color);
    tmpPainter.end();

绘制位置如图: 

调用Qt内部的模糊图像函数进行模糊图像处理:

    qt_blurImage(sourceBlured, radius, true);

在源上绘制此模糊图像:

    painter->drawImage(0, 0, sourceBlured);

大概位置如下:

效果:

重复画几次效果:

    for (int i = 0;i < 6;++i)
    {
        painter->drawImage(0, 0, sourceBlured);
    }

加上源图像:

    painter->drawPixmap(radius, radius, source);

总效果:

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Qt中,可以使用QSS(Qt Style Sheets)来美化界面的边框。 首先,需要在Qt的界面文件中使用样式表(QSS)来定义界面元素的样式。可以在QWidget、QDialog、QFrame等容器类的属性面板中找到"Style Sheet"选项,点击后可以进入编辑模式。 然后,在编辑模式中,可以使用CSS样式语法来定义界面元素的样式。针对边框的美化,可以使用border属性来设置,如"border: 2px solid red;"表示设置2像素宽度、红色的实线边框。还可以设置边框的圆角角度,使用"border-radius"属性来实现。 此外,还可以使用box-shadow属性来为界面元素添加阴影效果,例如设置"box-shadow: 2px 2px 5px gray;"可以添加2像素宽度、水平和垂直偏移量为2像素、模糊半径为5像素的灰色阴影。 最后,保存样式表后,将其应用到界面元素上,可以使用QWidget的setStyleSheet方法来设置样式表,或者在Qt Designer中直接设置。 除了QSS,也可以使用C++代码来实现界面边框的美化。通过继承QWidget或相关类,重写其paintEvent方法,在方法内使用QPainter绘制边框样式。 以上就是使用代码美化Qt界面边框的方法。通过定义样式表或重写绘图方法,可以实现个性化的边框样式,提升界面的美观性和用户体验。 ### 回答2: 在Qt中,我们可以使用代码来美化界面边框。下面是一些方法和技巧: 1. 使用QSS(Qt样式表)来设置边框的样式。在Qt中,我们可以使用QSS来定义界面元素的样式。可以使用`setStyleSheet()`方法将QSS样式应用于窗口或窗口部件。例如,可以使用`border: 2px solid red;`来定义边框为2像素宽的红色边框。 2. 自定义绘制边框。Qt提供了`paintEvent()`事件函数,允许我们在窗口或窗口部件上进行绘制操作。我们可以在`paintEvent()`函数中使用QPainter对象来绘制自定义的边框。例如,可以使用`QPainter::drawRect()`绘制一个矩形边框,并设置其线宽和颜色。 3. 使用样式类。Qt提供了许多样式类来帮助我们美化界面元素。例如,可以使用`QFrame`类来创建一个带边框的窗口部件,然后使用`setFrameStyle()`方法来设置边框样式。 4. 使用自定义样式插件。Qt允许我们创建自定义的样式插件来美化界面元素。我们可以使用Qt Creator来创建新的样式插件,并使用其提供的功能来设置边框的样式。 总的来说,Qt提供了多种方法来美化界面边框,我们可以根据需要选择合适的方法进行实现。无论是使用QSS、自定义绘制、样式类还是自定义样式插件,我们都可以通过代码来实现界面边框的美化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值