Add QQuickWidget::setClearColor()
authorLaszlo Agocs <laszlo.agocs@digia.com>
Thu, 24 Jul 2014 08:23:12 +0000 (10:23 +0200)
committerLaszlo Agocs <laszlo.agocs@digia.com>
Wed, 13 Aug 2014 12:34:50 +0000 (14:34 +0200)
And make qquickviewcomparison able to demonstrate how to create a
partially transparent QQuickWidget.

Avoid also recreating the QQuickView/QQuickWidget multiple times
when switching between the radio buttons.

[ChangeLog] Added QQuickWidget::setClearColor() in order to support
semi-transparent QQuickWidgets.

Change-Id: I319ad4afbe909530274d09f2a7fcff23730d6ebd
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h
examples/quick/quickwidgets/qquickviewcomparison/test.qml
src/quickwidgets/qquickwidget.cpp
src/quickwidgets/qquickwidget.h

index a8b5ecf..51b2a27 100644 (file)
@@ -49,7 +49,8 @@
 
 MainWindow::MainWindow()
     : m_currentView(0),
-      m_currentRootObject(0)
+      m_currentRootObject(0),
+      m_transparent(false)
 {
     QVBoxLayout *layout = new QVBoxLayout;
 
@@ -57,11 +58,12 @@ MainWindow::MainWindow()
     QVBoxLayout *vbox = new QVBoxLayout;
     m_radioView = new QRadioButton(tr("QQuickView in a window container (direct)"));
     m_radioWidget = new QRadioButton(tr("QQuickWidget (indirect through framebuffer objects)"));
-    vbox->addWidget(m_radioView);
     vbox->addWidget(m_radioWidget);
+    vbox->addWidget(m_radioView);
     m_radioWidget->setChecked(true);
-    connect(m_radioView, &QRadioButton::toggled, this, &MainWindow::updateView);
+    m_state = Unknown;
     connect(m_radioWidget, &QRadioButton::toggled, this, &MainWindow::updateView);
+    connect(m_radioView, &QRadioButton::toggled, this, &MainWindow::updateView);
     groupBox->setLayout(vbox);
 
     layout->addWidget(groupBox);
@@ -101,6 +103,11 @@ MainWindow::MainWindow()
     connect(m_checkboxOverlayVisible, &QCheckBox::toggled, m_overlayLabel, &QWidget::setVisible);
     layout->addWidget(m_checkboxOverlayVisible);
 
+    m_checkboxTransparent = new QCheckBox(tr("Transparent background in QQuickWidget"));
+    connect(m_radioWidget, &QCheckBox::toggled, m_checkboxTransparent, &QWidget::setEnabled);
+    connect(m_checkboxTransparent, &QCheckBox::toggled, this, &MainWindow::onTransparentChanged);
+    layout->addWidget(m_checkboxTransparent);
+
     setLayout(layout);
 
     updateView();
@@ -127,29 +134,45 @@ void MainWindow::switchTo(QWidget *view)
 
 void MainWindow::updateView()
 {
-    QString text = m_currentRootObject
-            ? m_currentRootObject->property("currentText").toString()
-            : QStringLiteral("Hello Qt");
-
-    QUrl source("qrc:qquickviewcomparison/test.qml");
     QSurfaceFormat format;
     format.setDepthBufferSize(16);
     format.setStencilBufferSize(8);
+    if (m_transparent)
+        format.setAlphaBufferSize(8);
     if (m_checkboxMultiSample->isChecked())
         format.setSamples(4);
 
-    if (m_radioView->isChecked()) {
+    State state = m_radioView->isChecked() ? UseWindow : UseWidget;
+
+    if (m_format == format && m_state == state)
+        return;
+
+    m_format = format;
+    m_state = state;
+
+    QString text = m_currentRootObject
+            ? m_currentRootObject->property("currentText").toString()
+            : QStringLiteral("Hello Qt");
+
+    QUrl source("qrc:qquickviewcomparison/test.qml");
+
+    if (m_state == UseWindow) {
         QQuickView *quickView = new QQuickView;
-        quickView->setFormat(format);
+        // m_transparent is not supported here since many systems have problems with semi-transparent child windows
+        quickView->setFormat(m_format);
         quickView->setResizeMode(QQuickView::SizeRootObjectToView);
         connect(quickView, &QQuickView::statusChanged, this, &MainWindow::onStatusChangedView);
         connect(quickView, &QQuickView::sceneGraphError, this, &MainWindow::onSceneGraphError);
         quickView->setSource(source);
         m_currentRootObject = quickView->rootObject();
         switchTo(QWidget::createWindowContainer(quickView));
-    } else {
+    } else if (m_state == UseWidget) {
         QQuickWidget *quickWidget = new QQuickWidget;
-        quickWidget->setFormat(format);
+        if (m_transparent) {
+            quickWidget->setClearColor(Qt::transparent);
+            quickWidget->setAttribute(Qt::WA_TranslucentBackground);
+        }
+        quickWidget->setFormat(m_format);
         quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
         connect(quickWidget, &QQuickWidget::statusChanged, this, &MainWindow::onStatusChangedWidget);
         connect(quickWidget, &QQuickWidget::sceneGraphError, this, &MainWindow::onSceneGraphError);
@@ -158,8 +181,11 @@ void MainWindow::updateView()
         switchTo(quickWidget);
     }
 
-    m_currentRootObject->setProperty("currentText", text);
-    m_currentRootObject->setProperty("multisample", m_checkboxMultiSample->isChecked());
+    if (m_currentRootObject) {
+        m_currentRootObject->setProperty("currentText", text);
+        m_currentRootObject->setProperty("multisample", m_checkboxMultiSample->isChecked());
+        m_currentRootObject->setProperty("color", QColor(m_transparent ? Qt::transparent : Qt::darkCyan));
+    }
 
     m_overlayLabel->raise();
 }
@@ -214,3 +240,9 @@ void MainWindow::onSceneGraphError(QQuickWindow::SceneGraphError error, const QS
 {
     m_labelStatus->setText(tr("Scenegraph error %1: %2").arg(error).arg(message));
 }
+
+void MainWindow::onTransparentChanged(bool enabled)
+{
+    m_transparent = enabled;
+    updateView();
+}
index c7bd514..c6df4c9 100644 (file)
@@ -57,11 +57,13 @@ public:
 
 protected:
     void resizeEvent(QResizeEvent*);
+
 private slots:
     void updateView();
     void onStatusChangedView(QQuickView::Status status);
     void onStatusChangedWidget(QQuickWidget::Status status);
     void onSceneGraphError(QQuickWindow::SceneGraphError error, const QString &message);
+    void onTransparentChanged(bool enabled);
 
 private:
     void switchTo(QWidget *view);
@@ -75,6 +77,18 @@ private:
     QObject *m_currentRootObject;
     QLabel *m_overlayLabel;
     QCheckBox *m_checkboxOverlayVisible;
+
+    enum State {
+        Unknown,
+        UseWidget,
+        UseWindow
+    } m_state;
+
+    QSurfaceFormat m_format;
+
+    QCheckBox *m_checkboxTransparent;
+
+    bool m_transparent;
 };
 
 #endif
index 2e8c830..5e11c3b 100644 (file)
@@ -44,7 +44,6 @@ import fbitem 1.0
 
 Rectangle {
     id: root
-    color: "lightBlue"
     property alias currentText: edit.text
     property alias multisample: fbitem.multisample
 
index 2541359..0a52198 100644 (file)
@@ -1115,4 +1115,23 @@ QImage QQuickWidget::grabFramebuffer() const
     return const_cast<QQuickWidgetPrivate *>(d_func())->grabFramebuffer();
 }
 
+/*!
+  Sets the clear \a color. By default this is an opaque color.
+
+  To get a semi- or fully transparent QQuickWidget, call this function with \a
+  color set to Qt::transparent and set the Qt::WA_TranslucentBackground widget
+  attribute.
+
+  \note The limitations for having widgets underneath visible that are described
+  in QOpenGLWidget::setFormat() apply also to QQuickWidget. In that case use
+  Qt::WA_AlwaysStackOnTop instead of Qt::WA_TranslucentBackground.
+
+  \sa QQuickWindow::setColor()
+ */
+void QQuickWidget::setClearColor(const QColor &color)
+{
+    Q_D(QQuickWidget);
+    d->offscreenWindow->setColor(color);
+}
+
 QT_END_NAMESPACE
index 6c3d63a..784286a 100644 (file)
@@ -96,6 +96,8 @@ public:
 
     QImage grabFramebuffer() const;
 
+    void setClearColor(const QColor &color);
+
 public Q_SLOTS:
     void setSource(const QUrl&);
     void setContent(const QUrl& url, QQmlComponent *component, QObject *item);