2014-05-18 14 views
6

posso aggiungere ombra per Widget:Qt: ombra intorno alla finestra

QGraphicsDropShadowEffect *bodyShadow = new QGraphicsDropShadowEffect; 
bodyShadow->setBlurRadius(9.0); 
bodyShadow->setColor(QColor(0, 0, 0, 160)); 
bodyShadow->setOffset(4.0); 
ui->widget->setGraphicsEffect(bodyShadow); 

Ma questa ombra sarà solo a sinistra e in basso. Ho bisogno di shadow around widget. Come aggiungere questo?

+0

Ho aggiornato la mia risposta in modo da poter vedere come l'effetto può essere applicato a un widget. – mhcuervo

risposta

14

È possibile creare l'effetto personalizzato. Condividerò un'implementazione che funziona.

customshadoweffect.h

#ifndef CUSTOMSHADOWEFFECT_H 
#define CUSTOMSHADOWEFFECT_H 

#include <QGraphicsDropShadowEffect> 
#include <QGraphicsEffect> 

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 <QPainter> 
// #include <QGraphicsEffect> 

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)); 
} 

sua applicazione (a un elemento grafico):

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

sua applicazione (a un widget bambino):

//... 
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); 
// ... 

Risultato: Effect applied to a child widget in a QMainWindow

2

Amo l'esempio di mhcuervo di come implementare un effetto personalizzato. Detto questo, è stato possibile ottenere un'ombra attorno al widget figlio utilizzando il codice, un offset di 0 e un raggio di sfocatura abbastanza grande da estenderlo attorno al widget figlio. (questo, usando Qt 5.4).

+0

Sì, questa risposta molto semplice ha funzionato anche per me, per i widget di geometria arbitraria. – Matt

Problemi correlati