PDA

View Full Version : [QtEmbedded] Translucent QGraphicsView with animated child widgets



zuck
5th January 2010, 10:43
Hi,

I'm working with Qt 4.6 and I've a QGraphicsView with some animated QGraphicsItems (I'm using QML). I want to make the window background transparent, so I can see the desktop under it.

I've tried this piece of code:



MainWindow::MainWindow(QWidget* parent)
: QmlView(parent)
{
this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_NoSystemBackground);
this->viewport()->setAutoFillBackground(false);
}


It works, but only for static widgets: the animated widget paints a trail on the window surface.

So, how can I erase this trail?
For example, how does KDE work with desktop semi-transparent animated widgets?

wysota
5th January 2010, 11:25
This is not how it works. WA_NoSystemBackground only means the background will not be initialized by the system when the widget is redrawn (hence the garbage left). Use WA_TranslucentBackground instead.

zuck
5th January 2010, 12:29
I know, but the result is the same in this case (Wa_TranslucentBackground set the WA_NoSystemBackground attribute too).

wysota
5th January 2010, 12:47
Does this work?


#include <QtGui>
#include <QPropertyAnimation>

class RectItem : public QObject, public QGraphicsRectItem {
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
public:
RectItem(const QRectF &rect, const QPen &pen, const QBrush &brush) : QObject(), QGraphicsRectItem(rect){
setPen(pen);
setBrush(brush);
}
};

#include "main.moc"

int main(int argc, char **argv){
QApplication app(argc, argv);
QGraphicsView view;
view.setAttribute(Qt::WA_TranslucentBackground);
view.viewport()->setAttribute(Qt::WA_TranslucentBackground);
QGraphicsScene scene(QRectF(0,0,1000,800));
view.setScene(&scene);
RectItem *rect = new RectItem(QRectF(0,0,200,100), QPen(Qt::red), Qt::blue);
scene.addItem(rect);
QPropertyAnimation *anim = new QPropertyAnimation(rect, "pos");
anim->setDuration(10000);
anim->setStartValue(scene.sceneRect().topLeft());
anim->setEndValue(scene.sceneRect().bottomRight());
anim->start();
view.show();
return app.exec();
}

zuck
5th January 2010, 13:02
No, the behaviour is the same.

Please, note that I'm working on Qt Embedded for Linux and not on Qt x11.

wysota
5th January 2010, 13:09
In that case I'd assume your device doesn't allow you to use translucency.

Please post your problem in the right section of the forum next time.

zuck
5th January 2010, 13:31
I'm sorry.

Well, currently the test is running on QVFB and not on the final device.

I've tried to run it with Qt x11 and the result is a window with a black background (the rectangle doesn't paint the trail but the background is fully opaque).

wysota
5th January 2010, 13:40
I've tried to run it with Qt x11 and the result is a window with a black background (the rectangle doesn't paint the trail but the background is fully opaque).

It probably means you have composition extension disabled in your X config. Run xdpyinfo and check if Composite is reported as one of the extensions.

zuck
5th January 2010, 16:00
Yes, I have it:



number of extensions: 30
BIG-REQUESTS
Composite <----------
DAMAGE
DOUBLE-BUFFER
DPMS
DRI2
GLX
Generic Event Extension
MIT-SCREEN-SAVER
MIT-SHM
NV-CONTROL
NV-GLX
RANDR
RECORD
RENDER
SECURITY
SHAPE
SYNC
X-Resource
XC-MISC
XFIXES
XFree86-DGA
XFree86-VidModeExtension
XINERAMA
XINERAMA
XInputExtension
XKEYBOARD
XTEST
XVideo
XVideo-MotionCompensation

wysota
5th January 2010, 16:11
The code I gave you works on my system (Linux 2.6 + KDE4 + Qt 4.6). So if it doesn't work on yours, this has to be a hardware or software configuration issue on your end.

zuck
5th January 2010, 16:46
Ok, thanks!

zuck
8th January 2010, 10:07
It now works on X11 with xcompmgr activated, but it still remains bugged on Qt Embedded :(

wysota
8th January 2010, 10:38
Because you have no compositing support there. It simply won't work. You can use QPixmap::grabWidget() to grab the image of the content beneath and render it as background of your widget above.

zuck
8th January 2010, 12:09
Yeah! This is the final working code (Qt 4.6):



#include <QtGui/QDesktopWidget>
#include <QtGui/QApplication>

MainWindow::MainWindow(QWidget* parent)
: QmlView(parent) // or QGraphicsView...
{
this->setWindowFlags(Qt::FramelessWindowHint);
this->setCacheMode(QGraphicsView::CacheBackground);
}

void MainWindow::showEvent(QShowEvent* event)
{
WId wid = QApplication::desktop()->winId();

int x = this->x();
int y = this->y();
int w = this->width();
int h = this->height();

this->setBackgroundBrush(QPixmap::grabWindow(wid, x, y, w, h));

QmlView::showEvent(event);
}


No "WA_TranslucentBackground" or "autoFillBackground(false)" are needed! :)