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 ?
问题:
回答1:
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_button1, *m_button2;
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();
}
回答2:
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.