Qt: shadow around window

前端 未结 2 1781
情书的邮戳
情书的邮戳 2021-01-02 09:11

I can add shadow to widget:

QGraphicsDropShadowEffect *bodyShadow = new QGraphicsDropShadowEffect;
bodyShadow->setBlurRadius(9.0);
bodyShadow->setColor         


        
2条回答
  •  醉梦人生
    2021-01-02 09:37

    You can create your custom effect. I'll share an implementation that works.

    customshadoweffect.h

    #ifndef CUSTOMSHADOWEFFECT_H
    #define CUSTOMSHADOWEFFECT_H
    
    #include 
    #include 
    
    class CustomShadowEffect : public QGraphicsEffect
    {
        Q_OBJECT
    public:
        explicit CustomShadowEffect(QObject *parent = 0);
    
        void draw(QPainter* painter);
        QRectF boundingRectFor(const QRectF& rect) const;
    
        inline void setDistance(qreal distance) { _distance = distance; updateBoundingRect(); }
        inline qreal distance() const { return _distance; }
    
        inline void setBlurRadius(qreal blurRadius) { _blurRadius = blurRadius; updateBoundingRect(); }
        inline qreal blurRadius() const { return _blurRadius; }
    
        inline void setColor(const QColor& color) { _color = color; }
        inline QColor color() const { return _color; }
    
    private:
        qreal  _distance;
        qreal  _blurRadius;
        QColor _color;
    };
    
    #endif // CUSTOMSHADOWEFFECT_H
    

    customshadoweffect.cpp

    #include "customshadoweffect.h"
    #include 
    // #include 
    
    CustomShadowEffect::CustomShadowEffect(QObject *parent) :
        QGraphicsEffect(parent),
        _distance(4.0f),
        _blurRadius(10.0f),
        _color(0, 0, 0, 80)
    {
    }
    
    QT_BEGIN_NAMESPACE
      extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );
    QT_END_NAMESPACE
    
    void CustomShadowEffect::draw(QPainter* painter)
    {
        // if nothing to show outside the item, just draw source
        if ((blurRadius() + distance()) <= 0) {
            drawSource(painter);
            return;
        }
    
        PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect;
        QPoint offset;
        const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
    
        // return if no source
        if (px.isNull())
            return;
    
        // save world transform
        QTransform restoreTransform = painter->worldTransform();
        painter->setWorldTransform(QTransform());
    
        // Calculate size for the background image
        QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance());
    
        QImage tmp(szi, QImage::Format_ARGB32_Premultiplied);
        QPixmap scaled = px.scaled(szi);
        tmp.fill(0);
        QPainter tmpPainter(&tmp);
        tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
        tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled);
        tmpPainter.end();
    
        // blur the alpha channel
        QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
        blurred.fill(0);
        QPainter blurPainter(&blurred);
        qt_blurImage(&blurPainter, tmp, blurRadius(), false, true);
        blurPainter.end();
    
        tmp = blurred;
    
        // blacken the image...
        tmpPainter.begin(&tmp);
        tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
        tmpPainter.fillRect(tmp.rect(), color());
        tmpPainter.end();
    
        // draw the blurred shadow...
        painter->drawImage(offset, tmp);
    
        // draw the actual pixmap...
        painter->drawPixmap(offset, px, QRectF());
    
        // restore world transform
        painter->setWorldTransform(restoreTransform);
    }
    
    QRectF CustomShadowEffect::boundingRectFor(const QRectF& rect) const
    {
        qreal delta = blurRadius() + distance();
        return rect.united(rect.adjusted(-delta, -delta, delta, delta));
    }
    

    Applying it (to a graphics item):

    // ...
    CustomShadowEffect *bodyShadow = new CustomShadowEffect();
    bodyShadow->setBlurRadius(20.0);
    bodyShadow->setDistance(6.0);
    bodyShadow->setColor(QColor(0, 0, 0, 80));
    item->setGraphicsEffect(bodyShadow);
    // ...
    

    Applying it (to a child widget):

    //...
    CustomShadowEffect *bodyShadow = new CustomShadowEffect();
    bodyShadow->setBlurRadius(20.0);
    bodyShadow->setDistance(6.0);
    bodyShadow->setColor(QColor(0, 0, 0, 80));
    ui->widget->setAutoFillBackground(true);
    ui->widget->setGraphicsEffect(bodyShadow);
    // ...
    

    Result: Effect applied to a child widget in a QMainWindow

提交回复
热议问题