Unable to make QQuickWidget background transparent without break stacking order

1.8k Views Asked by At

I have a problem making the QQuickWidget background transparent.

I want to place a QQuickWidget underneath a QWidget. The QQuickWidget uses a source qml file. When I worked with Qt 4.8, I used QDeclarativeView. Porting from Qt 4 to Qt 5, QDeclarativeView is no longer used. Therefore, I am usingQQuickWidget instead of QDeclarativeView, as follows:

 QWidget *mainWidget = new QWidget();
 mainWidget->setStyleSheet("background-image: url(:/background.png);");

 QQuickWidget *quick = new QQuickWidget(mainWidget);
 quick->setAttribute(Qt::WA_TranslucentBackground, true);
 quick->setAttribute(Qt::WA_AlwaysStackOnTop, true);
 quick->setClearColor(Qt::transparent);
 quick->setSource(QUrl("qrc:/image.qml"));

 QWidget *topWidget = new QWidget(mainWidget);
 topWidget->setStyleSheet("background-image: url(:/semitransparent.png);");

If I do:

setAttribute(Qt::WA_AlwaysStackOnTop, true);

then the background becomes transparent, but breaks the stacking order involving the other widgets underneath the QQuickWidget inside the same window.

I want to make a QQuickWidget transparent when it is underneath a QWidget. Is this possible? If not, what workarounds do you suggest?

(1) This is mainWidget's background image:

enter image description here

(2) This is QQuickWidget's background. qml file use this image:

enter image description here

(3) This is topWidget's background image:

enter image description here

(4) What I want:

enter image description here

(5) What I get when I set WA_AlwaysStackOnTop as false:

enter image description here

(6) What I get when I set WA_AlwaysStackOnTop as true:

enter image description here

2

There are 2 best solutions below

0
On

Official QT documentation here http://doc.qt.io/qt-5/qquickwidget.html says that breaking of the stacking order is to be expected:

When absolutely necessary, this limitation can be overcome by setting the Qt::WA_AlwaysStackOnTop attribute on the QQuickWidget. Be aware, however that this breaks stacking order. For example it will not be possible to have other widgets on top of the QQuickWidget, so it should only be used in situations where a semi-transparent QQuickWidget with other widgets visible underneath is required.

Also see this official blog entry: http://blog.qt.io/blog/2014/07/02/qt-weekly-16-qquickwidget/

This recent blog entry is for a feature that is new in QT 5.1: http://www.ics.com/blog/combining-qt-widgets-and-qml-qwidgetcreatewindowcontainer

Conclusion: What you are seeing is not a bug, but a known, recognized, advertised limitation of the QT framework.

My advice: Do not try to solve this with a hack, but redesign your UI approach. For example, maybe you can make topWidget alpha-blend (semi-transparent).

EDIT: For example, like this:

enter image description here

0
On

This is quite old but...

In many cases embedding a QML widget in a Qt Widgets application is useless unless you can make it transparent without breaking the stack order.

I do not have an implemented solution as at the end I did not need to do it. But I am explaining what was my approach in case someone want to give it a try.

1) Get a pixmap with parent background:

void QuickRoomWidget::showEvent(QShowEvent *event) 
{
    QPoint p1 = mapTo(parentWidget(), QPoint(0, 0));
    QPixmap px = parent->grab(QRect(p1, size()));
}

2) Use a QQuickImageProvider to pass image inside the QML:

https://doc.qt.io/qt-5/qquickimageprovider.html

https://doc.qt.io/qt-5/qtquick-imageprovider-example.html

3) Let the root item of your qml widget to draw the backgound using the pixmap.

Of course the performance of doing that will not be great so depending on where you need to use it probably will not be an option. But in my case this was not a problem.

If someone tries it please let me know if it worked!