PDA

View Full Version : Random crashes when using QPropertyAnimation on custom property



NaOH
21st October 2012, 04:59
Hi!
I'm fairly new at Qt and I'm getting really frustrated trying to make this work.
My problem is as follows:
I've created a derived class from QImage which I called "borderImage" which also inherits QObject. This class is itself a QImage but also has two QImages members "m_original" and "m_out". These members are created whithin the class constructor (passing a filename as an argument to the constructor). There is a function member of borderImage wich is "setAlpha" which changes the alpha of each pixel of "m_out" by picking first the color of the corresponding pixel at "m_original", then modifying its alpha and finally asigning this color to m_out's pixel. Also, "alpha" is defined as a property with the Q_PROPERTY macro, with alpha() as getter which simply returns the current alpha value, and setAlpha(int alpha) as the write function. Finally there is a class derived from QWidget which has a borderImage member that is drawn in every paintEvent.
The problem arises when trying to animate the "alpha" property. The problem itself is that the application crashes randomly when executing the animation.start() function. By trial and error I've determined that if the start() function is called "away" from the call to the constructor of the widget with the borderImage to be animated the application runs without any problem. Thus, I thought that the problem was in the constructor, and as a solution I tried to change the widget member borderImage to a pointer to a borderImage and initializing it in the constructor. I did the same with the QImage members of borderImage. None of these modifications worked. The applications continues to crash randomly when trying to start the animation. The only way to prevent this is, for instance, starting the animation after pressing a button, while the objects are created somewhere else in the code.

For clarification here is some parts of the code:
borderimage.h

#ifndef BORDERIMAGE_H
#define BORDERIMAGE_H

#include <QtGui>

class borderImage : public QObject, public QImage
{
Q_OBJECT
Q_PROPERTY(int alpha READ alpha WRITE setAlpha)
public:
borderImage(int width, int height, QWidget *parent = 0, const QString & filename = NULL);
borderImage(QImage image, QObject *parent=0);
QImage * getImage()
{ return m_out ;}
void setDistances(int top, int right, int bottom, int left);
void draw(int w, int h, float b_w);
int alpha() const
{return m_alpha;}
void setAlpha(int alpha);

private:
int m_top, m_right, m_bottom, m_left, m_w, m_h;
int m_alpha;
QImage *m_out;
QImage *m_original;
};

#endif // BORDERIMAGE_H

mainwidget.h


#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include "borderimage.h"

class mainWidget : public QWidget
{
Q_OBJECT

public:
mainWidget(QWidget *parent = 0);
~mainWidget();
borderImage * getBorde() { return borde; }

protected:
void paintEvent(QPaintEvent *event);


public slots:
void buttonClicked();
void timerEvent(QTimerEvent *event);

private:
void loadPlugins(QGridLayout *layout);
borderImage *borde;
QImage background;
QObjectList plugins;
};

#endif // MAINWIDGET_H

parts of borderimage.cpp

borderImage::borderImage(int width, int height, QWidget *parent, const QString & filename ):
QObject(parent), QImage(width, height, Format_ARGB32)
{
if (filename!=NULL)
{
m_original = new QImage(filename);
m_out = new QImage(filename);
}
this->fill(Qt::transparent);

//this->setDotsPerMeterX(10);
//this->setDotsPerMeterY(10);
}

...

void borderImage::setAlpha(int alpha)
{
int i;
int j;
QColor color;

for (i=0;i< (m_original->size().height());++i)
{
const QRgb * rgb = (QRgb *) m_original->scanLine(i);
QRgb * nuevo = (QRgb *) m_out->scanLine(i);
for (j=1; j<m_out->bytesPerLine();++j)
{
color.setRgba(*rgb);
if (color.alpha()>alpha)
{
color.setAlpha(alpha);
//color.toRgb();
//color.setRedF(color.redF()*alpha/255);
//color.setGreenF(color.greenF()*alpha/255);
//color.setBlueF(color.blueF()*alpha/255);
*nuevo = color.rgba();
}
++rgb;
++nuevo;
}
}

m_alpha=alpha;
//cout << alpha << "\n";

QWidget *papa = qobject_cast<QWidget *>(this->parent());
papa->update();
}

mainwidget.cpp

mainWidget::mainWidget(QWidget *parent)
: QWidget(parent)
{

...


borde = new borderImage(800,800,this,":/rsr/media/background.png");
borde->setDistances(50,50,50,50);
borde->setAlpha(200);

}

and the animation

QPropertyAnimation *animation = new QPropertyAnimation(pw->getBorde(),"alpha");
animation->setDuration(10);
animation->setStartValue(0);
animation->setEndValue(200);
animation->start
Where pw is a mainWidget. If that is called near the declaration of the mainWidget, it crashes randomly when run.

I can't figure out what the problem is...

Thanks in advance for your help!

PS: I've also noticed that the same problem occurs if I call setAlpha directly instead of animating the alpha property, therefore the problem must be in the setAlpha function (which is also called by the animation).

wysota
21st October 2012, 07:30
Why does your class inherit QImage?

NaOH
21st October 2012, 15:15
Even though there is a "getImage" function, it is not used. What is done is: in the function draw, a painter is created to paint on itself, and it paints several parts of m_out on differents parts of itself (being itself a QImage). Then in the widget class I directly pass the borderImage to drawImage as a QImage. Do you think it might be a problem with inheriting both QObject and QImage? If it is so, I can simply replace the getImage function to create a new QImage, paint on it from m_out, and finally return it, or create another private member which actually is the final image, and do the painting on that image instead of itself.

Thanks for the reply!

wysota
21st October 2012, 16:22
Do you think it might be a problem with inheriting both QObject and QImage?
Yes. QImage is usually copied and QObject can't be copied. If you pass your object as QImage somewhere, this might break QObject internals.

NaOH
21st October 2012, 19:04
Thanks! No longer inheriting QImage did the trick, thanks for the quick reply!