From a52404f25829ecf410eab39a6dcfdd69086de2b7 Mon Sep 17 00:00:00 2001 From: laserpants Date: Tue, 22 Mar 2016 08:23:04 +0300 Subject: [PATCH] add custom drop shadow class --- customshadoweffect.cpp | 76 +++++++++++++++++++++++++++++++++++++++++ customshadoweffect.h | 33 ++++++++++++++++++ qt-material-widgets.pro | 6 ++-- 3 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 customshadoweffect.cpp create mode 100644 customshadoweffect.h diff --git a/customshadoweffect.cpp b/customshadoweffect.cpp new file mode 100644 index 0000000..d2994e1 --- /dev/null +++ b/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/customshadoweffect.h b/customshadoweffect.h new file mode 100644 index 0000000..7a8825c --- /dev/null +++ b/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 9cb4fa3..749a782 100644 --- a/qt-material-widgets.pro +++ b/qt-material-widgets.pro @@ -31,7 +31,8 @@ SOURCES += main.cpp\ examples/appbarexamples.cpp \ examples/iconbuttonexamples.cpp \ examples/tabsexamples.cpp \ - examples/tableexamples.cpp + examples/tableexamples.cpp \ + customshadoweffect.cpp HEADERS += mainwindow.h \ style.h \ @@ -58,4 +59,5 @@ HEADERS += mainwindow.h \ examples/appbarexamples.h \ examples/iconbuttonexamples.h \ examples/tabsexamples.h \ - examples/tableexamples.h + examples/tableexamples.h \ + customshadoweffect.h