PDA

View Full Version : How to efficently fade out large QGraphicsItem.



momesana
27th September 2007, 17:01
Hi everybody and excuse me for asking so many questions lately :o

I have a QGraphicsRectItem that covers the whole QGraphicsView. I want to fade it out smoothly in about 600-1000 milliseconds. The problem is that it is flaky, even with QGLWidget as viewport. Can anybody tell me how to improve the performance and get rid of the annoying flicker?

Needs the QtOpenGL module to compile


#include <QApplication>
#include <QtGui>
#include <QtOpenGL>

class GraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
GraphicsScene(QObject *parent=0)
{
item = 0;
timeLine = 0;
}
private:
QGraphicsRectItem * item;
QTimeLine * timeLine;
public:
void initAnimation()
{
if (item == 0) {
item = new QGraphicsRectItem;
item->setRect(sceneRect());
addItem(item);
item->hide();
}
if (timeLine == 0) {
timeLine = new QTimeLine(750, this);
connect(timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animate(qreal)));
}
timeLine->start();
}
public slots:
void onViewRectChanged(QRectF r)
{
setSceneRect(r);
if (item)
item->setRect(r);
}
private slots:
void animate(qreal val)
{
(val < 1) ? item->show() : item->hide();
item->setPen(Qt::NoPen);
item->setBrush(QColor(0, 0, 0, (1-val)*255));
}
};

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent=0)
{
scene = new GraphicsScene();
view = new QGraphicsView(scene);
if (QGLFormat::hasOpenGL()) {
view->setViewport(new QGLWidget);
}
view->setViewportUpdateMode(QGraphicsView::FullViewportU pdate);
view->setOptimizationFlag(QGraphicsView::DontAdjustForAn tialiasing);
view->installEventFilter(this);
connect(this, SIGNAL(viewRectChanged(QRectF)), scene, SLOT(onViewRectChanged(QRectF)));

setCentralWidget(view);
}
virtual bool eventFilter(QObject *obj, QEvent *event)
{
if (obj == view && event->type() == QEvent::Resize) {
emit viewRectChanged(view->contentsRect());
}
return QMainWindow::eventFilter(obj, event);
}
protected:
void keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Space)
scene->initAnimation();
}

private:
GraphicsScene *scene;
QGraphicsView *view;
signals:
void viewRectChanged(QRectF);
};

int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow mw;
mw.resize(1024, 768);
mw.show();
return app.exec();
}
#include "main.moc"

dimuz
28th September 2007, 08:21
How about writing QGraphicsRectItem subclass and reimplementing its paint() function like this:



class MyRectItem : public QGraphicsRectItem
{
public:
void paint(QPainter *p, ....);
void setOpacity(qreal o) {mOpacity = o};
private:
qreal mOpacity;
}
MyRectItem::paint( QPainter *p .... )
{
p->save();
p->setOpacity(mOpacity);
QGraphicsRectItem::paint(p, ....);
p->restore();
}


and then calling setOpacity() from your animate() in scene and updating item?

I'm using that technique in one of my apps :)

momesana
28th September 2007, 10:59
I get the same result. The larger the window, the more flicker can be seen. The animation is cpu-intensive but works fine. When I write on a GLWidget even that problem isn't an issue but both ways I get annoying flicker :(.