Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt: How to create a clearly visible glow effect for a QLabel? (e.g. using QGraphicsDropShadowEffect)

Tags:

c++

graphics

qt

I am trying to add a glow effect to a QLabel so that it looks like the time display in the following picture:

enter image description here

I found out that you can "misuse" a QGraphicsDropShadowEffect for this:

QGraphicsDropShadowEffect * dse = new QGraphicsDropShadowEffect();
dse->setBlurRadius(10);
dse->setOffset(0);
dse->setColor(QColor(255, 255, 255));
ui.label->setGraphicsEffect(dse);

However, the resulting effect is too weak, you can barely see it:

enter image description here

Unfortunately, you can not modify the strength of the effect, only color and blur radius.

One idea would be to apply multiple QGraphicsDropShadowEffect to the label, so that it gets more visible due to overlapping. But calling ui.label->setGraphicsEffect(dse); will always delete any previous effects, i.e. I was not able to set multiple QGraphicsEffect to the same object.

Any ideas how you can create a clearly visible glow effect with Qt?

like image 890
manuel Avatar asked Mar 07 '15 18:03

manuel


1 Answers

Meanwhile, I tinkered my own graphics effect based on QGraphicsBlurEffect and using parts of this answer. If you know any better solutions, let me know.

qgraphicsgloweffect.h:

#pragma once
#include <QGraphicsEffect>
#include <QGraphicsBlurEffect>
#include <QGraphicsColorizeEffect>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPainter>

class QGraphicsGlowEffect :
  public QGraphicsEffect
{
public:
  explicit QGraphicsGlowEffect(QObject *parent = 0);

  QRectF boundingRectFor(const QRectF &rect) const;
  void setColor(QColor value);
  void setStrength(int value);
  void setBlurRadius(qreal value);
  QColor color() const;
  int strength() const;
  qreal blurRadius() const;

protected:
  void draw(QPainter* painter);

private:
  static QPixmap applyEffectToPixmap(QPixmap src, QGraphicsEffect *effect, int extent);
  int _extent = 5;
  QColor _color = QColor(255, 255, 255);
  int _strength = 3;
  qreal _blurRadius = 5.0;
};

qgraphicsgloweffect.cpp:

#include "QGraphicsGlowEffect.h"
#include <QtCore\qmath.h>

QGraphicsGlowEffect::QGraphicsGlowEffect(QObject *parent) : QGraphicsEffect(parent)
{
}

void QGraphicsGlowEffect::setColor(QColor value) {
  _color = value;
}

void QGraphicsGlowEffect::setStrength(int value) {
  _strength = value;
}

void QGraphicsGlowEffect::setBlurRadius(qreal value) {
  _blurRadius = value;
  _extent =  qCeil(value);
  updateBoundingRect();
}

QColor QGraphicsGlowEffect::color() const {
  return _color;
}

int QGraphicsGlowEffect::strength() const {
  return _strength;
}

qreal QGraphicsGlowEffect::blurRadius() const {
  return _blurRadius;
}

QRectF QGraphicsGlowEffect::boundingRectFor(const QRectF &rect) const {
  return QRect(
      rect.left() - _extent,
      rect.top() - _extent,
      rect.width() + 2 * _extent, 
      rect.height() + 2 * _extent);
}

void QGraphicsGlowEffect::draw(QPainter* painter) {
  QPoint offset;
  QPixmap source = sourcePixmap(Qt::LogicalCoordinates, &offset);
  QPixmap glow;

  QGraphicsColorizeEffect *colorize = new QGraphicsColorizeEffect;
  colorize->setColor(_color);
  colorize->setStrength(1);
  glow = applyEffectToPixmap(source, colorize, 0);

  QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
  blur->setBlurRadius(_blurRadius);
  glow = applyEffectToPixmap(glow, blur, _extent);

  for (int i = 0; i < _strength; i++)
    painter->drawPixmap(offset - QPoint(_extent, _extent), glow);
  drawSource(painter);
}

QPixmap QGraphicsGlowEffect::applyEffectToPixmap(
  QPixmap src, QGraphicsEffect *effect, int extent)
{
  if (src.isNull()) return QPixmap();
  if (!effect) return src;
  QGraphicsScene scene;
  QGraphicsPixmapItem item;
  item.setPixmap(src);
  item.setGraphicsEffect(effect);
  scene.addItem(&item);
  QSize size = src.size() + QSize(extent * 2, extent * 2);
  QPixmap res(size.width(), size.height());
  res.fill(Qt::transparent);
  QPainter ptr(&res);
  scene.render(&ptr, QRectF(), QRectF(-extent, -extent, size.width(), size.height()));
  return res;
}

Then you can use it like:

QGraphicsGlowEffect * glow = new QGraphicsGlowEffect();
glow->setStrength(4);
glow->setBlurRadius(7);
ui.label->setGraphicsEffect(glow);

This results in a nice glow effect:

enter image description here

like image 152
manuel Avatar answered Oct 31 '22 03:10

manuel