Toplevel Windows and Menus with Qt Quick

Published Friday August 26th, 2011 | by

We have already been writing shiny Qt Quick applications for a while now. Thanks to the people working on Qt Quick Desktop Components, Qt Quick is no longer interesting only on mobile platforms.

One of the fundamental things that was still missing, is the possibility to create a toplevel window directly inside a QML application. This is now possible without writing any additional C++ code, by using the new functionality provided in the Qt Quick Desktop Components repository.


The provided functionality includes:

  • Creating toplevel windows directly in QML
  • Define window modality and window decorations
  • Use QML bindings to resize / minimize / maximize a toplevel window
  • Adding menus with shortcuts to a toplevel window using QML items
  • Gather information about the screen geometry
  • Create property bindings across several windows

Lets take a brief look at those features.

A Toplevel Window
This is how a main window for your application can be created:

Window {
    id: mainWindow
    title: "My MainWindow"
    width: 640
    height: 480
    visible: true
}

If you want to create a child window, simply create another Window item inside the first one and set visible to true. Of course the child window will be deleted automatically as soon as the parent window is being closed.

Modality and Window Decorations
The modality or window decorations can be defined as well:

Window {
    ...
    windowDecoration: true
    modal: true
}

Size Constraints
If your window should have certain constraints on size you can apply these as follows:

Window {
    ...
    minimumWidth: 100
    minimumHeight: 100
    maximumHeight: 400
    maximumHeight: 400
}

Desktop Geometry
For a lot of applications the maximum window size is obviously tied to the available screen resolution and the available space on screen. Therefore we also export a Desktop item that delivers screenGeometry and availableGeometry per screen as well as a global screenCount. If you are interested in this information please take a look at the Gallery.qml example.

Minimize, Maximize and Normalize
In case you want your window to be minimized, normalized or maximized on a certain event, you can use the windowState property of the Window item to achieve this:

Button {
    ...
    onClicked: window.windowState = Qt.WindowMaximized
}

Property Bindings across several Windows
Due to the fact that the scenes of different windows still share the same declarative engine, it is perfectly viable to create property bindings across several windows. Simply refer to an object in a different window as you are already used to do with QML Items.

Window {
    ...
    Rectangle {
        id: myRect
        color: "green"
    }
    Window {
        ...
        MouseArea {
            anchors.fill: parent
            onClicked: myRect.color = "red"
        }
    }
}

 

Menus, Submenus and Shortcuts
Using the QML items MenuBar, Menu and MenuItem you can actually create native menubars and menus on desktop platforms. A Menu can have several MenuItems and of course also nested Menus.

MenuBar {
    Menu {
        text: "File"
        MenuItem {
             text: "Quit"
             shortcut: "Ctrl+Q"
             iconSource: images/quit.png
             onTriggered: Qt.quit()
        }
        ....
    }
    Menu {
        text: "Edit"
        Menu {
            text: "Advanced"
            MenuItem {
                text: "Maximize"
                shortcut: "Ctrl+M"
                iconSource: images/fullscreen.png
                onTriggered: window.windowState = Qt.WindowMaximized;
            }
        }
    }
    ...
}

Context Menus
Sometimes it is also nice to have a ContextMenu for certain options. In that case some javascript certainly needs to be involved.

ContextMenu {
    id: contextMenu
    MenuItem {
        text: "Copy"
        shortcut: "Ctrl+C"
        onTriggered: copy()
    }
    MenuItem {
        text: "Paste"
        shortcut: "Ctrl+V"
        onTriggered: paste()
    }
}
MouseArea {
    anchors.fill: parent
    acceptedButtons: Qt.RightButton
    onPressed: contextMenu.showPopup(mouseX,mouseY)
}

Getting rid of QmlViewer’s MainWindow
When using qmlviewer there will always be qmlviewer’s main window visible on the screen that can not be styled with additional Menus.
You can avoid this by using the provided qmldesktopviewer application instead. If you decide to use qmldesktopviewer for this purpose, make sure that your main QML file’s root item is a Window.

$ ./qmldesktopviewer/qmldesktopviewer examples/TopLevel.qml

Available Code and Examples
Currently all the code and examples can be found in the Qt Quick Components for Desktop repository in the master branch.

The repository also contains two examples that might be helpful.
There is the file examples/TopLevel.qml which wraps around the regular Gallery and adds menus and toplevel window behavior.
Further there is also examples/TopLevelBrowser.qml, a very simple webbrowser based on QtWebkit’s WebView Item. While this very simple browser might not give you the best browsing experience, it serves great as an example for opening and closing tabs or even new browser windows on the fly.

Have fun experimenting with this new feature set. And let us know how you like it.

Did you like this? Share it:

Posted in Labs, Qt, Qt Quick

57 comments to Toplevel Windows and Menus with Qt Quick

mgoetz says:

Congratulations :-)
The stuff looks good.
Maybe people will finally realize that QML is the more fun way to write UIs even for the desktop.

Alexis Menard says:

@mgoetz : totally. We are writing one every day and yes sometimes it is still missing features like this one, but with a bit of mix QWidget/QML you can achieve a LOT and much faster.

Scorp1us says:

Oh, Snap!

I was just complaining on lack of Desktop components and how unprofessional (as in desktop consistency) QML is.

This is a dream come true!

Nikolai says:

When will these components be integrated in Qt SDK?

It was the last thing which I missed in Qt Quick. Now there are no barriers to start working on GUI part of our application using QtQuick. Thanks!

Koh says:

Great!

So is that with QML we no longer have to deal with platform dependent UI, and that’s why the MeeGo Touch framework was scheduled to be dropped. Is these components would automatically have native look and feel?

Yury says:

I have got:
1> Moc’ing qdeclarativefolderlistmodel.h…
1>D:TEMPqt-components-desktopsrcstyleitemqdeclarativefolderlistmodel.h(64): error : Undefined interface

What’s wrong ?
Qt 4.7.2

Zeno Albisser says:

Thank you very much for the good feedback so far. :-)
@Nikolai : The desktop components are a research project. So we currently do not know, if they will ever be integrated into the SDK. But all that stuff is publicly available and works without any patches to Qt itself. So it should not be a problem to fetch these things separately and use it.

@Koh : I do not really understand how you are referring to Meego Touch. We try to provide a look and feel to as native as possible of course.

Keith Gardner says:

When creating a context menu, can you use the contextMenuEvent that QWidgets get to use? I don’t want to limit my application to just need a right mouse button to create a context menu in QML like I can with using widgets. Also, is there a way to abstract the key commands for copy and paste so that it can be platform independent as well?

Venemo says:

Why would anyone want to use the QML viewer app?

Is it possible to use these desktop components the same way we use the MeeGo/Harmattan components? In there, I just embed my QMLs into a .qrc and then I use a QDeclarativeView. (This is how the “Harmattan app” template generates them.) Is this possible with the desktop components?

And yeah, we surely want the desktop components to be part of Qt or the Qt SDK!

Zeno Albisser says:

@Yury : i briefly tried to reproduce that, but did not manage to do so. Obviously you are using windows. Can you tell me the exact compiler you are using? Did you build qt by yourself, are did you just download a binary package?

@Keith Gardner : you can actually trigger a context menu by every event that is available in QML (through javascript). But I don’t think that the contextMenuEvent is currently available. – This might be something we could add to the QmlDesktopViewer application.

@Venemo : The purpose of the QmlDesktopViewer is to allow people to write applications purely in QML. Without actually even touching C++. Further we might need something like that in future, to interface with native system events/behavior as mentioned above. Of course it is possible to imagine that in future we might use exactly such an app template as you described to provide the same functionality. But since Qt Quick Desktop Components is currently not a part of the SDK we simply provide QmlDesktopViewer.

Merinas says:

Hi, I can’t manage to use QmlDesktopViewer. I compiled it but when I tried to open a simple qml file it open nothing. I’m on mac, i tried droping my file on it, passing it (using terminal) to the exe file inside the .app

Zeno Albisser says:

@Merinas : “If you decide to use qmldesktopviewer for this purpose, make sure that your main QML file’s root item is a Window.” … is it? ;-)

Henrik Hartz says:

Very nice work!!

cpp says:

QML is very fancy tech, but I really hate its syntax pattern..(JS), like this

Window {
id: mainWindow
title: “My MainWindow”
width: 640
height: 480
visible: true
}

Why not use Cpp syntax like this:

Window mainWindow(“My MainWindow”,640,480,true); // so easy, so simple, so beautiful…

@cpp:i feel the same about c++.I love c++ and i hate js.
I am not negative on this one,but how can you write a compoment with 3 childs in it and 50 properties each?
It is not so beautiful with the c++ coding way.

I am sure that the desktop compoments will be added in the Qt SDK when they will be very very stable.After all Qt adds something only when it is very stable.

What is the situation with the machine resources?
UI with c++ vs UI with QML.
This is one is very important.

Yury says:

@Zeno Albisser
Yes, I am use windows.
If build from console (qmake+nmake+nmake install) works fine
The error happened only if I tried build in VS2010+VisualStudio Qt plugin.
It’s was fixed when I just disable moc for qdeclarativefolderlistmodel.h file

Mark says:

This is awesome! I was waiting for window things to become possible. Now the components are finally grown up enough to be used for real applications – imho! However there are a few QML issues that 1 still have.

1. Right now i fill my model in C++ (since i think C++ should be used for everything except defining the gui, there QML is fine) but in C++ we “only” have QStandardItemModel that is “somewhat” friendly towards QML and even then it needs a dozen tricks to make it usable. That needs to be made more friendly.

2. Distributing an app that uses the desktop components is really a pain! You need to: provide the Qt libs, the desktop components, the lib and the app itself.. A “Qt Runtime” that just has the Qt libs and the desktop components (along with that lib) would make distributing a qt app a lot easier.

Any way, good job and good post :) I hope to see more soon!

Zeno Albisser says:

@Giorgos Tsiapaliwkas : I currently don’t have any mesurements that compare Widgets to QML, but due to the fact of painting everything in a graphics scene i would assume QML to be quite a bit less performant. In Qt5 (which is currently not yet supported by the QML based toplevel widgets) we are heavily relying on scene graph. This will move the rendering over to the GPU and we are expecting a heavy performance boost.

@Mark : I totally agree with you, that it would be nice to provide such a solution that makes it much more easy to distribute an application. But let me mention again, that desktop components is still a research project and therefore it is currently lacking a seamless integration into the SDK.
I am not quite sure what you refer to about the lack of available models. I am not an expert there, but i’m pretty sure there is for example also a list and i think a table model.

minimoog77 says:

I am more interested how did you managed to render/creeate toplevel windows.

Tec says:

Very pleased to see some activity in the desktop space. Qt developments that aren’t cross platform just aren’t Qt.

Merinas says:

Zeno Albisser: yes it was. I use “TopLevel.qml”. I can’t either use qmlviewer because it don’t recognize QDestokp import and QmlDesktopViewer.

Zeno Albisser says:

@minimoog77 : i create a widget based window with a scene for each window item. The children of the window item then get reparented into the appropriate scene.

Zeno Albisser says:

@Merinas : did u also execute ‘make install’ ?
This will copy the plugin into the right position.

Merinas says:

I use qtcreator to build the desktop.pro I build it and tried to play it from QtCreator. I’ll try to do it from the command line.

Merinas says:

Okay thanks that work. Now I got a bug. When I move my mouse the content of the window is y-inverted for a fraction of second and go back to the normal. It did that a lot, so much that is unusable. I did some test, -no-opengl does nothing (I’m running on a mac) If I move my mouse slowly than usual nothing append.
This bug only appear on the tabs Widgets and range. When I click on the checkbox “Enable” on the toolbox the bug appear. When this box is checked. The bug doesn’t appear on the content of the “Widget” tab but only on the header.

Beside that, this is awesome, I’m really enjoying QML to make desktop app. I got another suggestion which only concern the mac plateform. To be perfect, we should be able to set the name of the app (this name is shown on the mac bar on the top of the screen right to the apple with the menu bar of the app.) It would be also great to be able to define an icon for the app (shown in the dock)
and be able to pack everything in a .app.

For now we should be able to do the two last without no line of c++ but this require a good knowledge of mac platform and time. And the first is only possible by rebuilding the QmlDesktopViewer.

Thanks again.

Merinas says:

In fact the bug also appear on the tabs “ItemsView” and “sidebar” if I scroll on it. But the window stay inverted while a scroll and go back to normal after.

see here http://img33.imageshack.us/img33/9602/capturedcran20110828114.png

Zeno Albisser says:

@Merinas : *huh*… that’s a pretty cool effect. ;-) I can’t reproduce it though i guess because i was mostly using a mac for development and never came across that bug. If you are using irc… can you find me on irc.freenode.net #qt-labs (zalbisser), i would like to know a bit more about your setup. ;-)

sebastian says:

great to see Qt Quick on the Desktop now, too.

however there still seems to be no reasonable way of creating a simple homescreen widget for Symbian, other than using WRT (which provides very limited functionality; actually I’m missing NFC at the moment).
I guess we will have to wait for Symbian Belle, at least, until Qt would also allow for creating homescreen widgets one day?

Mark says:

@Zeno http://www.developer.nokia.com/Community/Wiki/Using_QStandardItemModel_in_QML is about the only one. Remember, this is for passing a model to qml, not making a model in pure qml.
About performance. I know QML is on par or faster then QWidget and family but how about cpu and memory usge? I’m guessing both are higher since a javascript engine is used for QML. Numbers on this would be awesome!

Leaf says:

Thanks for your hard working

Zeno Albisser says:

@Merinas : i was actually looking into the issue about application name and application icon on mac already. The application item would be quite easy to implement. The bigger problem as far as i can see is the application name. Even though there is an api call called setProcessName on Mac, i don’t believe it will actually update the application name in the menu or in the dock. – This will need further investigation. But i think the only thing we could do there would be to change it at compile time and add it to the Info.plist file. That would then depend on an app profile and a real SDK integration… and is therefor (unfortunately) out of scope for the moment.

@sebastian : i am sorry i can’t answer your question. – This project is meant for desktop, and i am unfortunately not aware of latest state of symbian related development.

@Mark : i was briefly looking at the link you posted in google cache. And i think i understand what you mean. But honestly i think, if you are already writing code in C++ creating a simple subclass of an QAbstractItemModel derived class should be perfectly doable. – Of course there is always place for making things even more easy to use. And therefore i am very happy about such feedback of course! :-)

Jens says:

Zeno: congrats on the blog :)

Merinas: Which version of Qt are you testing against? I believe I have reported on this issue before so it should already be resolved but it might require you to try out a snapshot. Hopefully 4.7.4 and 4.8 should be out soon though, as they both contain important improvements for these components.

Mike says:

@sebastian

The public API for homescreen widgets is pretty poor in current versions of Symbian, but you CAN register and manipulate widgets directly from Qt without the need for WRT. It’s just restricted so you can only upload some text and an image, or an image. You could render the image in Qt, then just push that out to the widget each time it needs a refresh (which is what I’m guessing apps like battery monitor v2 do).

There is an example on the dev wiki (search for N8HomeScreenTest.zip) but unfortuanately it’s offline atm as the dev wiki is closed down :P

Hopefully in Belle we can write beautiful QML widgets instead of being limited to just pushing images to the homescreen…

Volker Hilsheimer says:

Is there a reason why there are both “Menu” and “ContextMenu” components? On the C++ side we have just QMenu. Less API to learn if there is just one class, esp if they are almost the same (Menu::text vs ContextMenu::id).
And speaking of QMenu – why “showPopup()” in the ContextMenu API, rather than just popup(), like in QMenu?

Zeno Albisser says:

@Volker Hilsheimer : The ContextMenu is currently also used for ComboBoxes and therefore extends the “normal” Menu item with some minor functions. I think the intention of showPopup() was to create a balanced api with hidePopup() as a counterpart. But i agree that we might want to rethink the ContextMenu api. – Thanks for the feedback. :)

Merinas says:

@Zeno : for the App name: it would be great if at least we could pass it by param at start. I don’t think dynamic update of the name would be useful.
Don’t you think it would be fun if we could write qmlviewer in qml on top of qmldesktopviewer ^^

Mark says:

@Zeno QAbstractItemModel can be seen as a table and works with QML, but what doesn’t work is adding, updating and deleting elements from it.. I have to make my own signal/slot connection for that and there seems to be no way (or i don’t know where to find it) to make an add or update work like this:

Model.updateData({id: index, name: “something”, description: “something else”});

Instead i have to do it like this:

Model.updateData(index, “something”, “something else”);

Which is also fine but right now i mix 2 things. The normal funtion passing stuff you all know from C, C++ and nearly all other languages. And the javascript way. I’d like to stick to using just 1 way. If you know how i can do that, please do tell me.

Regards,
Mark

Nils says:

Will the final ComboBoxes support models other than QML’s ListModel (most importantly QAbstractItemModel from C++)?

Last time I’ve looked at the sources the use of ContextMenu caused this limitation (QTCOMPONENTS-924)

Nils

Christoph says:

Great job! Some questions out of curiosity:
1. are there any plans for a QTreeView counterpart in QML?
2. how a parent-model child-model hierarchy might look like in QML?
3. when porting from QWidget to QML should we “flatten” our QAbstractItemModel(s) (e.g. split the hierarchy into flat lists)?
4. are there any plans for “observable lists” on QObject level (because QDeclarativeList is a real mess) so that we can ditch QAbstractItemModel and friends entirely?

Lilian says:

Is there any possibility to make border-less windows? For example, to make Close, Minimize and Maximize buttons by my self in QML and remove the borders, so there are no system Close, Minimize and Maximize buttons too.

Mark says:

When Nokia announced that they were switching to WP7 for their future devices, I immediately dropped Qt as my daily development environment. I only develop on two platforms: Mac OS X and the N900 (which was meant to get my apps ready for the N9).

I switched to Cocoa as it didn’t make much sense for me to use Qt for a pure Mac Application. However with the new developments of Qt and QML over the last while, I’ve become quite interested in Qt again.

The Qt Quick Desktop components really caught my eye. And even more so today now that we can write top level windows! I’m going to give this another shot as soon as a stable Qt-clang release comes out.

Very good work guys. I sure hope that these become more than a research project in the future.

Zeno Albisser says:

@Lilian : “Window { windowDecoration: false }” should do the job.

Jens says:

@christoph You might want to take a look at my post about table view http://labs.qt.nokia.com/2011/05/26/table-view-with-qt-quick/ . Of course we are looking into tree models too but since this project depends on qt declarative and it is not well supported at the moment, I am currently waiting to see what the Qt Quick 2.0 research results in before introducing API in desktop components.

Merinas says:

@Albisser I finish building the 474 and try with it and the one download, and I still got my bug.

maxoreli says:

Good news for Qt Quick.i have dowloaded source code and after building i have got this message:
Registering types now….
What do i do ?

Zeno Albisser says:

maxoreli: this is just a message that tells you that additional types have been registered to Qt Quick. – Everything is fine. :-)

maxoreli says:

Normally,i should see toplevelwindow appears at screen,but nothing appears.
In additionnal,i have got message like this:
package QtDesktop 0.1 is not installed…
And if i would integrate ‘mainwindow’ in my applications,what do i do
thanks for advance

Zeno Albisser says:

@maxoreli: after building the the desktop components, did you also execute “make install” ?
it seems that qmldesktopviewer cannot find the plugin.

maxoreli says:

No,i dont execute ‘make install’
please how will i do ?
My OS is window vista X86

Zeno Albisser says:

@maxoreli: i think on windows “nmake install” will do the job

Chetan says:

@Zeno Albisser: Hi, I am facing same problem which maxoreli is facing. and when i run desktop.pro from qt creator then i application window it shows “registerying types now”. and after copied “component” folder in “QtSDKDesktopQt4.7.3mingwimportsQtlabs” still showing -module “QtDesktop” is not installed- in qml viewer.
please help……..

Thanks in Advance

Unni says:

@Zeno Albisser: I am also facing the same problem reported by maxoreli & Chetan. When I tried to run the project from QtCreator (latest version), I get the message as given below.

Starting C:QtProjectsdesktop-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Releaseqmldesktopviewerreleaseqmldesktopviewer.exe…
registerying types now

I cannot see any windows or any other kind of outputs. When I try to close the qmldesktopviewer.exe tab (in Application Output pane), I get the message “qmldesktopviewer is still running. Force it to quit?”. Please help.

Zeno Albisser says:

@Chetan, @Unni: as i already mentioned, i believe that on windows “nmake install” should install the plugin to the right place. Unfortunately i don’t have a windows machine here right now to verify that. Once the plugin is installed in the right place, you have to run QmlDesktopViewer with the appropriate file as an argument, otherwise you will simply see nothing happening.
The appropriate files are either: TopLevel.qml or TopLevelBrowser.qml.
In case you are running QmlDesktopViewer from QtCreator, please make sure that you add the appropriate file as an argument in Run settings.

Chetan says:

@Zeno Albisser: Thanks a lot….. It works for me…….It is awesome…….
Thanks….Thanks…..Thanks….Thanks…..Thanks….Thanks…..

Dodobibi says:

Very nice, but is it a way for set QGLWidget to viewport of TopLevelWindow ?
I want use it with QtQuick3D

Thanks

Commenting closed.