Fade-Effekte

Code-Schnippsel, oder Tipps und Tricks, die einem beim Programmieren mit Qt helfen können.
Antworten
Alci
Beiträge: 70
Registriert: 24. März 2006 23:34

Fade-Effekte

Beitrag von Alci »

Hallo alle zusammen,

vor kurzem stand ich vor dem Problem, Fade-Effekte in meine Qt-Applikationen einbauen zu wollen. Leider hatte ich bis dahin nichts vernüftiges gefunden, was mir wirklich weiterhelfen konnte. Ich beschloss dann, in diesem Forum ein Topic aufzumachen und kam tatsächlich auf eine Lösung (danke an uhu01), die ich euch nicht vorenthalten möchte.

Der Ansatz schaut wie folgt aus: Es wird ein zusätzliches Widget erstellt, dass die gleichen Ausmaße (Breite, Höhe, Position und z. B. über setMask() definierte Masken) hat, wie das Widget, dass den Fade-Effekt haben soll. Dieses zusätzliche Widget ist erstmal nicht sichtbar (setVisible(false)).

Erst wenn der Benutzer eine Aktion ausführt, bei dem ein Fade-Effekt eintreten soll (z. B. MouseOver), kommt das zusätzliche Widget zum Einsatz. In diesem wird über einen Timer mehrere male ein update ausgelöst. Dieses update löst wiederum ein paintEvent aus, in dem das Fader-Widget mit einem bestimmten Alpha-Wert gezeichnet wird und der Alpha-Wert anschließend um einen bestimmten Wert verringert wird. Der Timer läuft solange, bis der Alpha-Wert <= 0 ist, denn dann ist das Fader-Widget komplett transparent.

Dieses Prinzip habe ich aus diesem Artikel. Ich habe aber einige Sachen nicht 1:1 übernommen. Mir hat z. B. nicht gefallen, dass das Fader-Widget immer wieder neu erzeugt wird. Deswegen habe ich einige Sachen verändert. Ich erzeuge das Fader-Widget immer nur einmal, und starte den Fade-Effekt mit der Methode Start() vom Fader-Widget.

Nun aber weg von der Theorie und hin zur Praxis:

FaderWidget.hpp

Code: Alles auswählen

#ifndef FADERWIDGET_HPP__
#define FADERWIDGET_HPP__

#include <QtGui\QWidget>
#include <QtCore\QTimer>
#include <QtGui\QColor>
#include <QtCore\QObject>
#include <QtGui\QPaintEvent>
#include <QtGui\QPainter>

class FaderWidget : public QWidget
{
	Q_OBJECT

	private:
		QWidget* m_pParent;
		QTimer m_Timer;
		QColor m_FadeColor;
		int m_FadeDuration;
		int m_CurrentAlpha;
		int m_StartAlpha;
		bool m_bStarted;

	public:
	    FaderWidget(QWidget *pParent);
		virtual ~FaderWidget(void);

		void SetFadeColor(QColor& FadeColor);
		int GetFadeDuration(void) const;
		void SetFadeDuration(int Duration);

		int GetStartAlpha(void) const;
		void SetStartAlpha(int Alpha);
		void SetFPS(int FPS);

	public slots:
	    void Start(void);
		void Stop(void);

	protected:
	    void paintEvent(QPaintEvent* pEvent);
};

inline void FaderWidget::SetFadeColor(QColor& FadeColor)
{
	m_FadeColor = FadeColor;
}

inline int FaderWidget::GetFadeDuration(void) const
{
	return m_FadeDuration;
}

inline void FaderWidget::SetFadeDuration(int Duration)
{
	m_FadeDuration = Duration;
}

inline int FaderWidget::GetStartAlpha(void) const
{
	return m_StartAlpha;
}

inline void FaderWidget::SetStartAlpha(int Alpha)
{
	m_StartAlpha = Alpha;
}

inline void FaderWidget::Stop(void)
{
	if (m_bStarted)
	{
		m_bStarted = false;
		m_Timer.stop();
		hide();
	}
}

inline void FaderWidget::SetFPS(int FPS)
{
	if (FPS > 0)
		m_Timer.setInterval((int)(1000 / FPS));
}

#endif
FaderWidget.cpp:

Code: Alles auswählen

#include "FaderWidget.hpp"

FaderWidget::FaderWidget(QWidget *pParent)
		: QWidget(pParent),
		m_pParent(pParent),
		m_Timer(this),
		m_FadeColor(Qt::white),
		m_FadeDuration(500),
		m_CurrentAlpha(150),
		m_StartAlpha(m_CurrentAlpha),
		m_bStarted(false)
{
	hide();
	m_Timer.setInterval(33); //=> 30 FPS
	connect(&m_Timer, SIGNAL(timeout()), this, SLOT(update()));
}

FaderWidget::~FaderWidget(void)
{
}

void FaderWidget::Start()
{
	if (m_bStarted)
	{
		m_bStarted = false;
		m_Timer.stop();
	}

	m_bStarted = true;
	if (m_pParent != NULL)
		resize(m_pParent->size());

	m_CurrentAlpha = m_StartAlpha;
	m_Timer.start();
	show();
}

void FaderWidget::paintEvent(QPaintEvent* pEvent)
{
    QPainter painter(this);
	m_FadeColor.setAlpha(m_CurrentAlpha);
    painter.fillRect(rect(), m_FadeColor);
	
	m_CurrentAlpha -= m_StartAlpha * m_Timer.interval() / m_FadeDuration;
	if (m_CurrentAlpha <= 0)
		Stop();
}
Hier ein Beispiel anhand eines Buttons, wie man das Fader-Widget verwendet:

MyButton.hpp:

Code: Alles auswählen

#include <QtGui\QPushButton>
#include "FaderWidget.hpp"
class MyButton : public QPushButton
{
private:
FaderWidget* m_pFaderWidget;

public:
MyButton(QWidget* pParent);
virtual ~MyButton(void);

protected:
void enterEvent(QEvent* pEvent);
};
MyButton.cpp:

Code: Alles auswählen

#include "MyButton.hpp"

MyButton::MyButton(QWidget* pParent)
: QPushButton(pParent)
{
//FaderWidget einmal erstellen
m_pFaderWidget = new FaderWidget(this);
}

MyButton::~MyButton(void)
{
}

//Event tritt bei Mauseintritt ein (eigentlich MouseEnter-Event)
void enterEvent(QEvent* pEvent)
{
if (m_pFaderWidget != NULL)
m_pFaderWidget->Start(); //Fade-Effekt starten
}
Im Prinzip könnte man das auch anders lösen, in dem man ein Fader-Widget als Oberklasse hat und alle Fade-Effekt-kompatiblen Widgets sollen von dieser abgeleitet werden. Diese Lösung wäre eigentlich fast besser. Ich werde aufjedenfall das Fader-Konzept weiter erweitern und bei Neuigkeiten mich nochmal melden. Aber es sollte aufjedenfall als Einstieg vorerstmal reichen.

Edit: Uups. Sorry, aber ich wollte das eigentlich unter "Snippets" posten. Bitte an den Admin, das zu verschieben.
MfG, Alci.

Aktuelle Projekte:
FModPlayer: Audio-Player auf Basis von FModEx
Epp.org: C++-IDE mit MinGW-Compiler

Entwickelt wird unter anderem mit Qt 4.1.4
Antworten