Meego Wiki
Views

QML/Creating a transparent window

From MeeGo wiki
Jump to: navigation, search

Contents

Overview

This tutorial describes how to create a transparent (or semi-transparent) Qt application with a QML GUI.

Note that I haven't found a way to do this in QML such that the application will display as transparent under the default qmlviewer application shipped with Qt Creator. Therefore, the approach taken here is to write a Qt application similar to the qmlviewer which does create a transparent window, then embed the QML UI in it. This approach was suggested by members of the QML mailing list (see this thread).

Finally, it looks as though Qt Creator 2.1 provides a QML project template which incorporates a custom viewer: http://labs.qt.nokia.com/2010/09/21/qt-quick-tooling/. Before long you will be able to create this type of application much more easily.

Pre-requisites

Basic understanding of Qt, QML, and Qt Creator: see this overview with pointers to Qt/QML documentation.

System setup

  • You need Qt and Qt Creator setup.
    You can set up a MeeGo toolchain if you like (as in those instructions), but if you're running an IA32 system and intend to deploy to an IA32 MeeGo system, you don't really need one: you can just use the Qt libraries installed by the MeeGo SDK.
  • You also need a compositing window manager running on the host, e.g. mutter (as used in MeeGo netbook) or compiz (available on distros like Fedora and Ubuntu).
    On Fedora, compiz will probably be installed by default, and you just need to enable it. If you are using a GNOME desktop, you can do this via the main menu: select System > Preferences > Desktop Effects. Check the Compiz checkbox to turn on compositing.

For reference, I used Fedora 13 to write this tutorial. I used a Qt Creator build from 2010-11-02, and a Qt build from 2010-11-18.

How to

First, we'll put in place all the project machinery to run a QML file in our own "viewer".

Then we'll make the changes so that the viewer window is semi-transparent.

As a bonus, we'll turn off window decorations to make the application really blend with the background.

Creating a QML "viewer"

  1. Create a new project using Qt Creator: Qt C++ Project, Mobile Qt Application is a good basis.
  2. In the project, delete the mainwindow.ui file (we'll be using QML for the UI).
  3. Next, create a (very) simple QML user interface file:
    1. Right-click on the project name, and select Add New... from the context menu.
    2. In the dialog box, select Qt then Qt QML File.
    3. Click Choose.
    4. Enter ui as the name of the file.
    5. Click Next, accept the defaults, and click Finish.
    6. Replace the content of the new ui.qml file with this:
      import Qt 4.7
      
      Rectangle {
        width: 640
        height: 480
        color: "red"
      }
      
  4. Next we need a way to locate the QML file from the Qt application. To do this, we'll add a Qt resource file (.qrc). This enables binary files to be added to the application executable in a platform-independent way, as well as providing access via a resource name.
    Add the resource file as follows:
    1. Right-click on the project, choose Add New..., and select Qt, Qt Resource file.
    2. Step through the dialog boxes. Use resources for the file name.
    3. Once the file is ready, click on the Add button and select Add Prefix from the drop-down. Use / as the prefix.
    4. Still in the resources.qrc file, click the Add button again and select Add Files. This pops up a file chooser: inside it, click on the ui.qml file and then click Open. The selected file should should now appear under the / prefix.
  5. Now the application needs to be able to use classes from the QDeclarative library. To make this library visible to the project, edit the .pro file for your project, adding declarative to the QT line, like this:
    QT       += core gui declarative
    
  6. To load the QML file, we'll modify the existing MainWindow class.
    1. First edit the header file, mainwindow.h. The change here is to make the ui member variable an instance of QDeclarativeView:
      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QtDeclarative/QDeclarativeView>
      
      namespace Ui {
          class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      private:
          QDeclarativeView *ui;
      };
      
      #endif // MAINWINDOW_H
      

      Note that we also added an include for the <QtDeclarative/QDeclarativeView> header at the top of the file.

    2. Finally, edit the mainwindow.cpp file, so that the constructor for the MainWindow loads the QML file (via the Qt Resource mechanism):
      #include "mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent)
      {
        ui = new QDeclarativeView;
        ui->setSource(QUrl("qrc:/ui.qml"));
        setCentralWidget(ui);
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      

It should now be possible to run the application (click on the big green arrow, bottom-left corner), which should display as a red rectangle:

Qml-transparent-window-basic-ui.png

Making the viewer semi-transparent

  1. First, make ui.qml slightly more interesting:
    import Qt 4.7
    
    Rectangle {
      width: 640
      height: 480
      color: "#7bffff00"
    
      Text {
        text: "I'm walking in the air"
        anchors.centerIn: parent
      }
    }
    

    Note here that the color property is set to an RGBA (color with alpha) string, similar to the hexadecimal color strings used to define HTML colors. The alpha component is defined by the first two digits after the hash symbol (7b), in this case setting the alpha component to 123 (to make it completely transparent, set this to 00; for completely opaque, set it to ff). The other digits define a yellow color for the rectangle.

  2. Even if you run the code now, despite the alpha setting, you still get a solid window. This is because you're still seeing the white MainWindow underneath the pale yellow, semi-transparent rectangle. The solution is to modify mainwindow.cpp, so that the constructor sets the main window itself to be transparent:
    #include "mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
    {
      /* you need both these lines for a transparent main window */
      setAttribute(Qt::WA_TranslucentBackground);
      setStyleSheet("background:transparent;");
    
      ui = new QDeclarativeView;
      ui->setSource(QUrl("qrc:/ui.qml"));
      setCentralWidget(ui);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

Now when you run the application, it should look something like this:

Qml-transparent-window-actually-transparent.png

A couple of things to note:

  • The background you can see through the window is the QML code the viewer is running.
  • There are no window decorations on the screenshot, but this is because of compiz, rather than the application. When compiz is switched on, screenshots lose window decorations. For the previous screenshot, I had compiz turned off, so you could see the window decorations. See below for more on window decorations.

Turning off window decorations

If you want to make your application run without window decorations, so it really blends with the background, add a setWindowsFlags(Qt::FramelessWindowHint) method call to the MainWindow constructor:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
  setAttribute(Qt::WA_TranslucentBackground);
  setStyleSheet("background:transparent;");
  
  /* turn off window decorations */
  setWindowFlags(Qt::FramelessWindowHint);

  ui = new QDeclarativeView;
  ui->setSource(QUrl("qrc:/ui.qml"));
  setCentralWidget(ui);
}

MainWindow::~MainWindow()
{
    delete ui;
}

Just for fun, here is the app running with transparent background and no window decorations on MeeGo netbook (under the mutter compositor):

Qml-transparent-on-meego.png

Personal tools