diff --git a/lib/customshadoweffect.cpp b/lib/customshadoweffect.cpp new file mode 100644 index 0000000..d2994e1 --- /dev/null +++ b/lib/customshadoweffect.cpp @@ -0,0 +1,76 @@ +#include "customshadoweffect.h" +#include + +CustomShadowEffect::CustomShadowEffect(QObject *parent) + : QGraphicsEffect(parent), + _distance(4.0), + _blurRadius(10.0), + _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 +{ + const qreal delta = blurRadius() + distance(); + return rect.united(rect.adjusted(-delta, -delta, delta, delta)); +} diff --git a/lib/customshadoweffect.h b/lib/customshadoweffect.h new file mode 100644 index 0000000..7a8825c --- /dev/null +++ b/lib/customshadoweffect.h @@ -0,0 +1,33 @@ +/* + * http://stackoverflow.com/questions/23718827/qt-shadow-around-window + */ +#ifndef CUSTOMSHADOWEFFECT_H +#define CUSTOMSHADOWEFFECT_H + +#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 diff --git a/qt-material-widgets.pro b/qt-material-widgets.pro index 749a782..94f9986 100644 --- a/qt-material-widgets.pro +++ b/qt-material-widgets.pro @@ -23,6 +23,7 @@ SOURCES += main.cpp\ components/table.cpp \ lib/ripple.cpp \ lib/rippleoverlay.cpp \ + lib/customshadoweffect.cpp \ examples/frame.cpp \ examples/examplelist.cpp \ examples/flatbuttonexamples.cpp \ @@ -31,8 +32,7 @@ SOURCES += main.cpp\ examples/appbarexamples.cpp \ examples/iconbuttonexamples.cpp \ examples/tabsexamples.cpp \ - examples/tableexamples.cpp \ - customshadoweffect.cpp + examples/tableexamples.cpp HEADERS += mainwindow.h \ style.h \ @@ -51,6 +51,7 @@ HEADERS += mainwindow.h \ components/table.h \ lib/ripple.h \ lib/rippleoverlay.h \ + lib/customshadoweffect.h \ examples/frame.h \ examples/examplelist.h \ examples/flatbuttonexamples.h \ @@ -59,5 +60,4 @@ HEADERS += mainwindow.h \ examples/appbarexamples.h \ examples/iconbuttonexamples.h \ examples/tabsexamples.h \ - examples/tableexamples.h \ - customshadoweffect.h + examples/tableexamples.h