yellowmat
31st March 2006, 16:39
Hi !
I wrote a widget class to manage animations. It is possible to set the displaying speed with a timer, and on each timeout I display an image.
When I have to animation object (one uppon the other), the one which is behind the other is not repainted successfully.
Actually my drawing code is in the function displayImage ... but I think it shouldn't be the right way to process.
Something more conform should be to implement an update or repaint call in the function displayImage and then implement the drawing of the image in the function paintEvent but it is flickering.
Here is the code I actually use to, so if someone could help me to find out how to do, it would be great.
// Constructor / Destructor
CAnimation::CAnimation(QWidget* parent/*=0*/, const char* name/*=0*/):
QWidget(parent, name, Qt::WStyle_Customize|Qt::WStyle_NoBorder),
timer(0),
mode(PlayModeForeward),
loopStopIndex(1),
loopCurrentIndex(0),
speed(500),
imageStartIndex(0),
imageStopIndex(0),
imageCurrentIndex(0),
playingStatus(Idle),
displayingStatus(Hidden),
transparency(false)
{
// Create the timer
if( timer == 0 )
timer = new QTimer(this, "timer");
// Connect the timer signal to the animation object slot
connect(timer, SIGNAL(timeout()), SLOT(timerTick()));
}
CAnimation::~CAnimation()
{
// Stop the timer if active
if( timer->isActive() )
timer->stop();
// Delete the timer
if( timer != 0 )
{
delete timer;
timer = 0;
}
// Clear the image names
images.clear();
}
// Slots
int CAnimation::displayImage(const QPixmap& pixmap)
{
if( transparency )
{
if ( pixmap.mask() )
this->setMask( *pixmap.mask() );
}
QRect rect(this->rect());
bitBlt(this, rect.topLeft(), &pixmap);
return 0;
}
void CAnimation::timerTick()
{
switch(mode)
{
case(CAnimation::PlayModeForeward):
{
/************************************************** ************************************************** ****************
Two cases
CASE 1 : if the image current index is not the image stop index then we increment it and display the image.
CASE 2 : if the image current index is the image stop index, we must take care if the sequence must be looped.
************************************************** ************************************************** *****************/
// CASE 1
if( imageCurrentIndex == imageStartIndex )
{
// Notify
emit sequenceStarted();
}
if( imageCurrentIndex < imageStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the current index
imageCurrentIndex++;
}
// CASE 2
else if( imageCurrentIndex == imageStopIndex )
{
if( loopStopIndex == 0 )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
else if( loopCurrentIndex < loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the loop index
loopCurrentIndex++;
// Reset the image current index
imageCurrentIndex = imageStartIndex;
}
else if( loopCurrentIndex == loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
}
}
break;
case(CAnimation::PlayModeBackward):
{
/************************************************** ************************************************** ****************
Two cases
CASE 1 : if the image current index is not the image stop index then we decrement it and display the image.
CASE 2 : if the image current index is the image stop index, we must take care if the sequence must be looped.
************************************************** ************************************************** *****************/
// CASE 1
if( imageCurrentIndex == imageStartIndex )
{
// Notify
emit sequenceStarted();
}
if( imageCurrentIndex > imageStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the current index
imageCurrentIndex--;
}
// CASE 2
else if( imageCurrentIndex == imageStopIndex )
{
if( loopStopIndex == 0 )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
else if( loopCurrentIndex < loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the loop index
loopCurrentIndex++;
// Reset the image current index
imageCurrentIndex = imageStartIndex;
}
else if( loopCurrentIndex == loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
}
}
break;
default:
break;
}
}
int CAnimation::start()
{
// Check conditions
// ... TO DO
// Set initial values
imageCurrentIndex = imageStartIndex;
loopCurrentIndex = 0;
// Start timer
timer->start(speed);
// Update state
this->setPlayingStatus(CAnimation::Started);
// Notify
emit animationStarted();
return 0;
}
int CAnimation::stop()
{
// Stop the timer
timer->stop();
// Update the state
this->setPlayingStatus(CAnimation::Stopped);
// Notify
emit animationStopped();
return 0;
}
int CAnimation::pause()
{
// Stop the timer
timer->stop();
// Update the state
this->setPlayingStatus(CAnimation::Paused);
// Notify
emit animationPaused();
return 0;
}
int CAnimation::resume()
{
// Start the timer
timer->start(speed);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Notify
emit animationResumed();
return 0;
}
int CAnimation::finish()
{
// Stop the timer
timer->stop();
// Reset values
imageCurrentIndex = imageStartIndex;
loopCurrentIndex = 0;
// Update the state
this->setPlayingStatus(CAnimation::Finished);
// Notify
emit animationFinished();
return 0;
}
int CAnimation::showAnim()
{
// Show the widget
this->show();
// Update the state
this->setDisplayingStatus(CAnimation::Shown);
// Notify
emit animationShown();
return 0;
}
int CAnimation::hideAnim()
{
// Hide the widget
this->hide();
// Update the state
this->setDisplayingStatus(CAnimation::Hidden);
// Notify
emit animationHidden();
return 0;
}
Thanks in advance.
I wrote a widget class to manage animations. It is possible to set the displaying speed with a timer, and on each timeout I display an image.
When I have to animation object (one uppon the other), the one which is behind the other is not repainted successfully.
Actually my drawing code is in the function displayImage ... but I think it shouldn't be the right way to process.
Something more conform should be to implement an update or repaint call in the function displayImage and then implement the drawing of the image in the function paintEvent but it is flickering.
Here is the code I actually use to, so if someone could help me to find out how to do, it would be great.
// Constructor / Destructor
CAnimation::CAnimation(QWidget* parent/*=0*/, const char* name/*=0*/):
QWidget(parent, name, Qt::WStyle_Customize|Qt::WStyle_NoBorder),
timer(0),
mode(PlayModeForeward),
loopStopIndex(1),
loopCurrentIndex(0),
speed(500),
imageStartIndex(0),
imageStopIndex(0),
imageCurrentIndex(0),
playingStatus(Idle),
displayingStatus(Hidden),
transparency(false)
{
// Create the timer
if( timer == 0 )
timer = new QTimer(this, "timer");
// Connect the timer signal to the animation object slot
connect(timer, SIGNAL(timeout()), SLOT(timerTick()));
}
CAnimation::~CAnimation()
{
// Stop the timer if active
if( timer->isActive() )
timer->stop();
// Delete the timer
if( timer != 0 )
{
delete timer;
timer = 0;
}
// Clear the image names
images.clear();
}
// Slots
int CAnimation::displayImage(const QPixmap& pixmap)
{
if( transparency )
{
if ( pixmap.mask() )
this->setMask( *pixmap.mask() );
}
QRect rect(this->rect());
bitBlt(this, rect.topLeft(), &pixmap);
return 0;
}
void CAnimation::timerTick()
{
switch(mode)
{
case(CAnimation::PlayModeForeward):
{
/************************************************** ************************************************** ****************
Two cases
CASE 1 : if the image current index is not the image stop index then we increment it and display the image.
CASE 2 : if the image current index is the image stop index, we must take care if the sequence must be looped.
************************************************** ************************************************** *****************/
// CASE 1
if( imageCurrentIndex == imageStartIndex )
{
// Notify
emit sequenceStarted();
}
if( imageCurrentIndex < imageStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the current index
imageCurrentIndex++;
}
// CASE 2
else if( imageCurrentIndex == imageStopIndex )
{
if( loopStopIndex == 0 )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
else if( loopCurrentIndex < loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the loop index
loopCurrentIndex++;
// Reset the image current index
imageCurrentIndex = imageStartIndex;
}
else if( loopCurrentIndex == loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
}
}
break;
case(CAnimation::PlayModeBackward):
{
/************************************************** ************************************************** ****************
Two cases
CASE 1 : if the image current index is not the image stop index then we decrement it and display the image.
CASE 2 : if the image current index is the image stop index, we must take care if the sequence must be looped.
************************************************** ************************************************** *****************/
// CASE 1
if( imageCurrentIndex == imageStartIndex )
{
// Notify
emit sequenceStarted();
}
if( imageCurrentIndex > imageStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the current index
imageCurrentIndex--;
}
// CASE 2
else if( imageCurrentIndex == imageStopIndex )
{
if( loopStopIndex == 0 )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
else if( loopCurrentIndex < loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Increment the loop index
loopCurrentIndex++;
// Reset the image current index
imageCurrentIndex = imageStartIndex;
}
else if( loopCurrentIndex == loopStopIndex )
{
// Display the image
this->displayImage(images[imageCurrentIndex]);
// Notify
emit frameDisplayed(imageCurrentIndex);
emit sequenceFinished();
// Finish the animation
this->finish();
}
}
}
break;
default:
break;
}
}
int CAnimation::start()
{
// Check conditions
// ... TO DO
// Set initial values
imageCurrentIndex = imageStartIndex;
loopCurrentIndex = 0;
// Start timer
timer->start(speed);
// Update state
this->setPlayingStatus(CAnimation::Started);
// Notify
emit animationStarted();
return 0;
}
int CAnimation::stop()
{
// Stop the timer
timer->stop();
// Update the state
this->setPlayingStatus(CAnimation::Stopped);
// Notify
emit animationStopped();
return 0;
}
int CAnimation::pause()
{
// Stop the timer
timer->stop();
// Update the state
this->setPlayingStatus(CAnimation::Paused);
// Notify
emit animationPaused();
return 0;
}
int CAnimation::resume()
{
// Start the timer
timer->start(speed);
// Update the state
this->setPlayingStatus(CAnimation::Started);
// Notify
emit animationResumed();
return 0;
}
int CAnimation::finish()
{
// Stop the timer
timer->stop();
// Reset values
imageCurrentIndex = imageStartIndex;
loopCurrentIndex = 0;
// Update the state
this->setPlayingStatus(CAnimation::Finished);
// Notify
emit animationFinished();
return 0;
}
int CAnimation::showAnim()
{
// Show the widget
this->show();
// Update the state
this->setDisplayingStatus(CAnimation::Shown);
// Notify
emit animationShown();
return 0;
}
int CAnimation::hideAnim()
{
// Hide the widget
this->hide();
// Update the state
this->setDisplayingStatus(CAnimation::Hidden);
// Notify
emit animationHidden();
return 0;
}
Thanks in advance.