Following up with the suggestions from wysota (thanks wysota), I have a similar requirement when using a QLabel with a pixmap. The following code segment is my
attempt at following wysota's instructions for using a subclass in combination with a
QPropertyAnimation. I can tell from breakpoints to the setOpacity API, that the API is being called properly, but the rendering within the paintEvent never displays the QLabel pixmap with any change to the transparency. The pixmap I am using with my QLabel is a PNG with alpha content. For those of you interested in attempting a similar quest, this might be a good starting point. It would be good to the community to get this
to work as it is most useful.
m_propAnimationFadeOverscrollTop = new QPropertyAnimation(ui->overscrollTop, "windowOpacity");
m_propAnimationFadeOverscrollTop->setDuration(5000);
m_propAnimationFadeOverscrollTop->setStartValue(0.0);
m_propAnimationFadeOverscrollTop->setEndValue(1.0);
m_propAnimationFadeOverscrollTop->start();
class LabelAnimate
: public QLabel{
Q_OBJECT
Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow)
public:
m_alpha(0),
opacity(0.0)
{
// Start with the image completely transparent
UpdateAlphaChannel(m_alpha);
}
public:
qreal windowOpacity() const
{
return opacity;
}
void setWindowOpacity(qreal opacity)
{
opacity = qBound(qreal(0.0), opacity, qreal(1.0));
setAttribute(Qt::WA_WState_WindowOpacitySet);
}
void fadeMore()
{
if (m_alpha > 0)
{
UpdateAlphaChannel(--m_alpha);
}
}
void fadeLess()
{
if (m_alpha < 255)
{
UpdateAlphaChannel(++m_alpha);
}
}
int getAlpha() { return m_alpha; }
void setAlpha(int alpha) { UpdateAlphaChannel(alpha); }
protected:
{
// From wysota: setting up a painter and calling QPainter::setOpacity() before calling the base class implementation
// or if this doesn't work, call the base class implementation first and then use QPainter::setCompositionMode() to
// setup a composition mode that will allow you to paint the alpha channel to what is already painted using an opacity of
// your choice
#ifdef METHOD1
p.begin(this);
p.setOpacity(opacity);
p.end();
// Call base class
#else
// Call base class
p.begin(this);
p.
setCompositionMode(QPainter::CompositionMode_Clear);
//::CompositionMode_DestinationIn);
p.end();
#endif
}
{
p.
fillRect(alpha.
rect(),
QColor(val, val, val
));
p.end();
px.setAlphaChannel(alpha);
return px;
}
void UpdateAlphaChannel(int alpha)
{
const QPixmap *px
= this
->pixmap
();
// Check for NULL before converting to reference
if (px != 0)
{
// Convert pointer to reference
// Change alpha using reference argument
setAlpha(pm, alpha);
}
}
private:
int m_alpha; // Current alpha level
qreal opacity; // opacity
};
m_propAnimationFadeOverscrollTop = new QPropertyAnimation(ui->overscrollTop, "windowOpacity");
m_propAnimationFadeOverscrollTop->setDuration(5000);
m_propAnimationFadeOverscrollTop->setStartValue(0.0);
m_propAnimationFadeOverscrollTop->setEndValue(1.0);
m_propAnimationFadeOverscrollTop->start();
class LabelAnimate : public QLabel
{
Q_OBJECT
Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow)
public:
LabelAnimate(QWidget *parent = 0): QLabel(parent),
m_alpha(0),
opacity(0.0)
{
// Start with the image completely transparent
UpdateAlphaChannel(m_alpha);
}
public:
qreal windowOpacity() const
{
return opacity;
}
void setWindowOpacity(qreal opacity)
{
opacity = qBound(qreal(0.0), opacity, qreal(1.0));
setAttribute(Qt::WA_WState_WindowOpacitySet);
}
void fadeMore()
{
if (m_alpha > 0)
{
UpdateAlphaChannel(--m_alpha);
}
}
void fadeLess()
{
if (m_alpha < 255)
{
UpdateAlphaChannel(++m_alpha);
}
}
int getAlpha() { return m_alpha; }
void setAlpha(int alpha) { UpdateAlphaChannel(alpha); }
protected:
void paintEvent(QPaintEvent *event)
{
// From wysota: setting up a painter and calling QPainter::setOpacity() before calling the base class implementation
// or if this doesn't work, call the base class implementation first and then use QPainter::setCompositionMode() to
// setup a composition mode that will allow you to paint the alpha channel to what is already painted using an opacity of
// your choice
#ifdef METHOD1
QPainter p;
p.begin(this);
p.setOpacity(opacity);
p.end();
// Call base class
QLabel::paintEvent(event);
#else
// Call base class
QLabel::paintEvent(event);
QPainter p;
p.begin(this);
p.setCompositionMode(QPainter::CompositionMode_Clear);
//::CompositionMode_DestinationIn);
p.end();
#endif
}
QPixmap &setAlpha(QPixmap &px, int& val)
{
QPixmap alpha = px;
QPainter p(&alpha);
p.fillRect(alpha.rect(), QColor(val, val, val));
p.end();
px.setAlphaChannel(alpha);
return px;
}
void UpdateAlphaChannel(int alpha)
{
const QPixmap *px = this->pixmap();
// Check for NULL before converting to reference
if (px != 0)
{
// Convert pointer to reference
QPixmap pm(*px);
// Change alpha using reference argument
setAlpha(pm, alpha);
}
}
private:
int m_alpha; // Current alpha level
qreal opacity; // opacity
};
To copy to clipboard, switch view to plain text mode
Added after 1 28 minutes:
Further observation, I am not getting repaints for the pixmap as changes are made via the QPropertyAnimation to setOpacity despite my calls to update() and refresh()
Any ideas?
void setWindowOpacity(qreal opacity)
{
qDebug() << "LabelAnimate::setWindowOpacity:" << opacity;
opacity = qBound(qreal(0.0), opacity, qreal(1.0));
setAttribute(Qt::WA_WState_WindowOpacitySet);
// Force repaint
this->update();
this->repaint();
}
void setWindowOpacity(qreal opacity)
{
qDebug() << "LabelAnimate::setWindowOpacity:" << opacity;
opacity = qBound(qreal(0.0), opacity, qreal(1.0));
setAttribute(Qt::WA_WState_WindowOpacitySet);
// Force repaint
this->update();
this->repaint();
}
To copy to clipboard, switch view to plain text mode
Bookmarks