tags:

views:

60

answers:

2

I want to progressively decrease the opacity of a QPushButton over a time of 2 seconds to complete transparency. For that I used the QPropertyAnimation class and used the property "windowOpacity" of the button to achieve the effect. But that worked only for a standalone QPushButton. When I assigned a parent to the button, the effect disappeared. Is there any way of achieving the same effect for child buttons ?

+2  A: 

The windowOpacity property only applies to top level windows so it won't help you with animating transparency on child widgets unfortunately.

Standard controls are a bit problematic as well as there are many considerations contributing to their final appearance. There are many approaches you could take but they will all involve a certain amount of coding. There is no easy way :)

To set the transparency of a QPushButton, you would need to either set a stylesheet for it, or change some of the properties of the palette. Since neither of these options are directly usable by a QPropertyAnimation, you can create your own custom property and animate that.

Below is some code that specifies a custom property for a MainWindow called alpha. The alpha value is used to set the alpha portion of the button color. With this property in place, we can use QPropertyAnimation to animate it. The result is a button that fades in and out. This only handles the buttons background and not the text but it should provide a starting point for you.

MainWindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QPushButton>

class MainWindow : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(int alpha READ alpha WRITE setAlpha);

public:
    MainWindow();
    virtual ~MainWindow();

private:
    int m_alpha;
    QPushButton * m_button;

    int alpha() const;
    void setAlpha(const int a_alpha);
};

#endif  /* MAINWINDOW_H */

MainWindow.cpp: (Updated to include stylesheet transparency example)

#include <QPlastiqueStyle>
#include <QPropertyAnimation>

#include "MainWindow.h"

MainWindow::MainWindow() :
    m_button1(0),
    m_button2(0),
    m_alpha(255)
{
    resize(200, 200);
    QPalette windowPalette(palette());
    windowPalette.setBrush(QPalette::Background, QBrush(QColor(200, 0, 0)));
    setPalette(windowPalette);

    m_button1 = new QPushButton(this);
    m_button1->setText("Palette Transparency");
    m_button1->setAutoFillBackground(false);
    // NOTE: Changing the button background color does not work with XP Styles
    // so we need to use a style that allows it.
    m_button1->setStyle(new QPlastiqueStyle());

    m_button2 = new QPushButton(this);
    m_button2->move(0, 50);
    m_button2->setText("Stylesheet Transparency");
    m_button2->setAutoFillBackground(false);
    m_button2->setStyle(new QPlastiqueStyle());

    QPropertyAnimation *animation = new QPropertyAnimation(this, "alpha");
    animation->setDuration(1000);
    animation->setKeyValueAt(0, 255);
    animation->setKeyValueAt(0.5, 100);
    animation->setKeyValueAt(1, 255);
    animation->setLoopCount(-1);
    animation->start();
}

MainWindow::~MainWindow()
{
}

int MainWindow::alpha() const
{
    return m_alpha;
}

void MainWindow::setAlpha(const int a_alpha)
{
    m_alpha = a_alpha;

    QPalette buttonPalette(m_button1->palette());
    QColor buttonColor(buttonPalette.button().color());
    buttonColor.setAlpha(m_alpha);
    buttonPalette.setBrush(QPalette::Button, QBrush(buttonColor));
    m_button1->setPalette(buttonPalette);

    QString stylesheet("background-color: rgba(0,200,0," + QString::number(m_alpha) + ");");
    m_button2->setStyleSheet(stylesheet);

}

main.cpp:

#include <QtGui/QApplication>

#include "MainWindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MainWindow m;
    m.show();

    return app.exec();
}
Arnold Spence
Thanks a lot. It worked but not if I set the color through a stylesheet. Any hint as to what functions to manipulate in order to make the borders and the text also transparent ?
Daud
Everything you should need is available in the documentation for QPalette. There is a lot there but some reading and experimenting with the code I provided will get you there. That's all I did :)
Arnold Spence
I've updated the example code to include a button with stylesheet based transparency since you mentioned that you couldn't get that to work.
Arnold Spence
A: 

I faced the same problem a while ago and came to basically the same solution(manipulating the controls palette). But, while the helper property in the MainWindow is surely a quick and easy solution, it's a dirty one too. So, at least for larger and reoccurring usage it seamed much more appropriate to create a new animation class covering those needs. This isn't much more code(simply inherit QAbstractAnimation, move that palette stuff in there and pass the target control as a parameter into that class) but it keeps your parent control(like the mainwindow-class) free from such animation implementation details which surely don't belong in there.

TheSUNSTAR