PDA

View Full Version : Set opacity in Linux



Momergil
17th June 2014, 13:21
Hello!

I want to add some "fading" effect (I guess that's the name) in a pop-up widget in one of my applications for Linux when the widget is both shown and hidden. I'ld guess that the normal way of doing this is to add a QPropertyAnimation that would change the window's opacity from 0 to 255 in a period of time (lets say 500 ms).

Now the problem is that in the Linux I'm using window opacity is not available; so I both can't change the window opacity with QProperyAnimation, nor with setWindowOpacity(qreal).


The question: how do I do this, then? I tried with stylesheet (connecting a slot to the QProperyAnimation and changing the window's background-color alpha channel from 0 to 255) but it doesn't seem to be interesting setting a new stylesheet so quickly (calling a set QString method frequently), nor is it elegant.

I wonder if there is another way of doing this for this circumstance that is not by stylesheet?


I'm glad for any help,

Momergil


Note: using Qt 4.8 for ARM

anda_skoa
17th June 2014, 15:05
Now the problem is that in the Linux I'm using window opacity is not available

Yes, it is.

Just tried with


#include <QApplication>
#include <QLabel>
#include <QPropertyAnimation>

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

QLabel label("Hello World");

label.show();

QPropertyAnimation fade(&label, "windowOpacity");
fade.setStartValue(1.0);
fade.setEndValue(1.0);
fade.setKeyValueAt(0.5, 0.0);
fade.setDuration(5000);

fade.start();

return app.exec();
}


A window with the label in it appears, fades out and fades in again.

Cheers,
_

Momergil
17th June 2014, 16:13
Hello anda_skoa!

First, thanks for the reply.

Second, I was quite interested when you provided a direct use of QPropertyAnimation as a solution to my problem, since (as I mentioned above) I've tried that solution before without success. I decided to give a try, nonetheless, and for my surprise your code actually worked.

I began to make comparisons between your QPropertyAnimation implementation and mine (having done the proper adaptations) and despite various checkings and debugs, I simply couldn't make my code work; the fade effect simply don't happen.

So the code I'm using is below. As you may see, it's supposed to be a replacement of QMessageBox that is activated once the user clicks in a place, when the show1() method is called. It should than start the fade effect on poBaseWidget, and once the user clicks on it, a new closing fade should occur. Could you please tell me why it's not working?

Thanks,

Momergil



class MessageFrame : public QFrame
{
Q_OBJECT
Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText)
Q_ENUMS(Icon)
Q_ENUMS(TextType)

public:
enum Icon { Question, Information, Warning, Critical };
enum TextType { ScreenDescription, GeneralText };

MessageFrame(QWidget* parent = 0) :
QFrame(parent),
poBaseWidget(new QFrame(this))
{
setObjectName("MessageFrame");
setGeometry(0,20,800,460);

//
poBaseWidget->setGeometry(120,0,560,100);
poBaseWidget->setStyleSheet("* { background-color: rgb(192,192,192);"
"background-origin: content;"
"border: 2px rgb(128,128,127);"
"border-radius: 10px; }");

//
iconLabel = new QLabel(poBaseWidget);
iconLabel->resize(32,32);
setIcon(Information);

//
textLabel = new QLabel(poBaseWidget);
textLabel->setWordWrap(true);
textLabel->setMaximumSize(textLabel->parentWidget()->width() - iconLabel->width() - 20, textLabel->parentWidget()->height() - 10);
textLabel->resize(textLabel->maximumSize());

//
startFadeAnimation = new QPropertyAnimation(poBaseWidget, "windowOpacity",this);
startFadeAnimation->setStartValue(0.0);
startFadeAnimation->setEndValue(1.0);
startFadeAnimation->setDuration(5000);

stopFadeAnimation = new QPropertyAnimation(poBaseWidget, "windowOpacity",this);
stopFadeAnimation->setStartValue(1.0);
stopFadeAnimation->setEndValue(0.0);
stopFadeAnimation->setDuration(5000);

connect(stopFadeAnimation,SIGNAL(finished()),this, SLOT(close()));

//
poBaseWidget->installEventFilter(this);

hide(); //hide();
}

virtual ~MessageFrame()
{
poBaseWidget->removeEventFilter(this);
}

inline QString currentText() const;

void setCurrentText(const QString& text);

void setIcon(const Icon icon);

static void information(const QString& text);

static void warning(const QString& text);

static void critical(const QString& text);

private:
QLabel* textLabel,
* iconLabel;
QPropertyAnimation* startFadeAnimation,
* stopFadeAnimation;
QString screenText;
QFrame* poBaseWidget;

protected:
bool eventFilter(QObject *obj, QEvent *ev)
{
if (obj == poBaseWidget && ev->type() == QEvent::MouseButtonRelease)
{
stopFadeAnimation->start();
return true;
}
else
return QFrame::eventFilter(obj,ev);
}

public slots:
void show1(const TextType type = GeneralText)
{
switch (type)
{
case GeneralText: //last set text
break;

case ScreenDescription:
// setCurrentText(screenText);
break;
}

show();

startFadeAnimation->start();
}

inline void setScreenText(const QString& text) { screenText = text; }

/////////////////////////////////////////////////////
/// SINGLETON STUFF - DON'T TOUCH
public:
static void start(QWidget* parent = 0);

static void MessageFrameDestroy();

inline static MessageFrame& instance();

private:
static MessageFrame* poInstance;
};

wysota
18th June 2014, 07:42
You are animating windowOpacity of poBaseWidget instead of your MessageFrame instance. Only top-level windows can have their windowOpacity manipulated.

Momergil
18th June 2014, 12:21
You are animating windowOpacity of poBaseWidget instead of your MessageFrame instance. Only top-level windows can have their windowOpacity manipulated.

Oh, I remember reading that in the manual; I didn't noticed I was doing that in my code. Anyway, why is that so? And, well, if the method show by anda_skoa is valid only for top-level windows, I'll restate my first question to: is there a way to create such a "fade" effect that is not by stylesheet and that is valid for any widget I want to apply the effect regardless of being a top level widget or not?

anda_skoa
18th June 2014, 12:49
So you want the content of the window to fade, not the window itself?

Maybe usingQGraphicsOpacityEffect on the widget which you want to fade.

Cheers,
_

Momergil
18th June 2014, 14:02
So you want the content of the window to fade, not the window itself?

Exactly, and your suggestion worked perfectly. Thanks!

Momergil