On this page

Starter layouts for Qt Quick desktop applications

Every Qt Bridges application uses Qt Quick for its user interface, no matter which programming language provides the backend. If you are new to Qt Quick and QML, deciding how to arrange the window is usually the first hurdle.

This page collects typical desktop application layouts. Each one is a small, self-contained Main.qml that you can paste into a new project, run, and then grow. They intentionally contain placeholders instead of real content and no backend logic, so you can focus on the structure.

Before you start

All the examples use three imports, for example:

import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts
  • Qt Quick provides the basic visual items, such as Item and Rectangle.
  • Qt Quick Controls provides ready-made controls and window parts, such as ApplicationWindow, Button, ToolBar, and TabBar. The part after QtQuick.Controls selects a style, which decides how those controls look.
  • Qt Quick Layouts provides RowLayout, ColumnLayout, GridLayout, FlexboxLayout, and StackLayout, which resize and position their children automatically.

A few rules of thumb apply to all layouts below:

  • Use ApplicationWindow as the root item. It gives you slots for header, footer, and menuBar.
  • Inside a layout, use Layout.fillWidth and Layout.fillHeight to share the available space, instead of setting positions by hand.
  • Use anchors.fill: parent only for a single child that should cover its parent.
  • Give windows a minimumWidth and minimumHeight so your layout never collapses.

Note: The colored Rectangle items are only placeholders. Replace them with your own components as soon as you have them.

Note: Each layout uses a different Qt Quick Controls style, so you can see some of the options. The style is not tied to the layout: to use another one, change the import QtQuick.Controls.<Style> line, for example to QtQuick.Controls.Fusion. The Basic, Fusion, Material, Universal, and FluentWinUI3 styles are available on all platforms. See Styling Qt Quick Controls for the full list.

1. Single page

A single centered area of content. This is the best start for small tools, settings dialogs, login screens, and forms.

Shown with the Material style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts

ApplicationWindow {
    id: root
    width: 480
    height: 360
    minimumWidth: 320
    minimumHeight: 240
    visible: true
    title: qsTr("Single page")

    ColumnLayout {
        anchors.centerIn: parent
        width: Math.min(parent.width - 48, 360)
        spacing: 12

        Label {
            text: qsTr("Sign in")
            font.pixelSize: 24
        }
        TextField {
            Layout.fillWidth: true
            placeholderText: qsTr("User name")
        }
        TextField {
            Layout.fillWidth: true
            placeholderText: qsTr("Password")
            echoMode: TextInput.Password
        }
        Button {
            Layout.fillWidth: true
            text: qsTr("Continue")
            highlighted: true
        }
    }
}

A toolbar at the top, a status bar at the bottom, and the content in between. This is the classic desktop application frame.

Shown with the Fusion style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Fusion
import QtQuick.Layouts

ApplicationWindow {
    width: 800
    height: 600
    minimumWidth: 400
    minimumHeight: 300
    visible: true
    title: qsTr("Header, content, footer")

    header: ToolBar {
        RowLayout {
            anchors.fill: parent
            anchors.leftMargin: 8
            anchors.rightMargin: 8

            ToolButton { text: qsTr("New") }
            ToolButton { text: qsTr("Open") }
            ToolButton { text: qsTr("Save") }
            Item { Layout.fillWidth: true }  // pushes what follows to the right
            ToolButton { text: qsTr("Help") }
        }
    }

    footer: ToolBar {
        Label {
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            anchors.leftMargin: 8
            text: qsTr("Ready")
        }
    }

    // The window content fills the space between header and footer
    ScrollView {
        anchors.fill: parent
        contentWidth: availableWidth

        Label {
            width: parent.width
            padding: 16
            wrapMode: Text.Wrap
            text: qsTr("Your main content goes here.")
        }
    }
}

3. Sidebar and content

A side column for navigation or a file tree, and a main column for the content. The SplitView lets users resize both columns by dragging the handle.

Shown with the Universal style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Universal
import QtQuick.Layouts

ApplicationWindow {
    width: 900
    height: 600
    minimumWidth: 500
    minimumHeight: 300
    visible: true
    title: qsTr("Sidebar and content")

    SplitView {
        anchors.fill: parent

        // Side column
        Pane {
            SplitView.preferredWidth: 220
            SplitView.minimumWidth: 140
            SplitView.maximumWidth: 400

            ListView {
                id: sidebar
                anchors.fill: parent
                model: [qsTr("Inbox"), qsTr("Drafts"), qsTr("Sent"), qsTr("Trash")]
                currentIndex: 0
                delegate: ItemDelegate {
                    required property int index
                    required property string modelData
                    width: ListView.view.width
                    text: modelData
                    highlighted: ListView.isCurrentItem
                    onClicked: sidebar.currentIndex = index
                }
            }
        }

        // Main column
        Pane {
            SplitView.fillWidth: true

            Label {
                text: qsTr("Showing: %1").arg(sidebar.currentItem
                                              ? sidebar.currentItem.text : "")
                font.pixelSize: 20
            }
        }
    }
}

4. Tabs

Top-level sections selected with a TabBar. Use it when the sections are equally important and the user switches between them often. A StackLayout shows only the page that matches the current tab.

Shown with the Fluent (FluentWinUI3) style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.FluentWinUI3
import QtQuick.Layouts

ApplicationWindow {
    width: 700
    height: 500
    minimumWidth: 400
    minimumHeight: 300
    visible: true
    title: qsTr("Tabs")

    header: TabBar {
        id: bar
        TabButton { text: qsTr("Overview") }
        TabButton { text: qsTr("Data") }
        TabButton { text: qsTr("Settings") }
    }

    StackLayout {
        anchors.fill: parent
        currentIndex: bar.currentIndex

        Pane { Label { text: qsTr("Overview page") } }
        Pane { Label { text: qsTr("Data page") } }
        Pane { Label { text: qsTr("Settings page") } }
    }
}

Note: In a real application, move each page into its own .qml file, for example OverviewPage.qml, and use it as OverviewPage {}.

5. Master-detail

A list of items on the left and the details of the selected item on the right. This is the natural fit for data coming from a backend model, such as contacts, messages, or products.

Shown with the Material style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts

ApplicationWindow {
    width: 800
    height: 500
    minimumWidth: 480
    minimumHeight: 300
    visible: true
    title: qsTr("Master-detail")

    // Replace this with a model exposed by your backend
    ListModel {
        id: items
        ListElement { name: "Alice"; email: "alice@example.com" }
        ListElement { name: "Bob"; email: "bob@example.com" }
        ListElement { name: "Carol"; email: "carol@example.com" }
    }

    RowLayout {
        anchors.fill: parent
        spacing: 0

        ListView {
            id: list
            Layout.preferredWidth: 240
            Layout.fillHeight: true
            clip: true
            model: items
            currentIndex: 0
            delegate: ItemDelegate {
                required property int index
                required property string name
                width: ListView.view.width
                text: name
                highlighted: ListView.isCurrentItem
                onClicked: list.currentIndex = index
            }
            ScrollBar.vertical: ScrollBar {}
        }

        ToolSeparator { Layout.fillHeight: true }

        Pane {
            Layout.fillWidth: true
            Layout.fillHeight: true

            ColumnLayout {
                visible: list.currentIndex >= 0
                spacing: 8

                Label {
                    text: list.currentIndex >= 0 ? items.get(list.currentIndex).name : ""
                    font.pixelSize: 22
                }
                Label {
                    text: list.currentIndex >= 0 ? items.get(list.currentIndex).email : ""
                }
            }
            Label {
                anchors.centerIn: parent
                visible: list.currentIndex < 0
                text: qsTr("Select an item")
                opacity: 0.6
            }
        }
    }
}

6. Drawer navigation

A menu that slides in from the side, plus a StackView to move between pages and come back. It works well when you have many destinations, or when the window can be narrow.

Shown with the Universal style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Universal
import QtQuick.Layouts

ApplicationWindow {
    width: 600
    height: 500
    minimumWidth: 320
    minimumHeight: 300
    visible: true
    title: qsTr("Drawer navigation")

    header: ToolBar {
        RowLayout {
            anchors.fill: parent

            ToolButton {
                text: stack.depth > 1 ? "‹" : "☰"  // back or menu
                onClicked: stack.depth > 1 ? stack.pop() : drawer.open()
            }
            Label {
                Layout.fillWidth: true
                text: stack.currentItem ? stack.currentItem.title : ""
                font.bold: true
            }
        }
    }

    Drawer {
        id: drawer
        width: Math.min(parent.width * 0.7, 280)
        height: parent.height

        Column {
            anchors.fill: parent

            ItemDelegate {
                width: parent.width
                text: qsTr("Home")
                onClicked: { stack.replace(homePage); drawer.close() }
            }
            ItemDelegate {
                width: parent.width
                text: qsTr("About")
                onClicked: { stack.replace(aboutPage); drawer.close() }
            }
        }
    }

    StackView {
        id: stack
        anchors.fill: parent
        initialItem: homePage
    }

    Component {
        id: homePage
        Page {
            title: qsTr("Home")
            Button {
                anchors.centerIn: parent
                text: qsTr("Open details")
                onClicked: stack.push(aboutPage)
            }
        }
    }

    Component {
        id: aboutPage
        Page {
            title: qsTr("About")
            Label { anchors.centerIn: parent; text: qsTr("About this app") }
        }
    }
}

7. Dashboard grid

Cards arranged in a grid that changes the number of columns with the window width. Use it for overviews, galleries, and status pages.

Shown with the Fluent (FluentWinUI3) style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.FluentWinUI3
import QtQuick.Layouts

ApplicationWindow {
    width: 900
    height: 600
    minimumWidth: 360
    minimumHeight: 300
    visible: true
    title: qsTr("Dashboard grid")

    ScrollView {
        anchors.fill: parent
        contentWidth: availableWidth

        GridLayout {
            width: parent.width
            columns: Math.max(1, Math.floor(width / 240))
            rowSpacing: 16
            columnSpacing: 16

            Repeater {
                model: 8

                Frame {
                    required property int index
                    Layout.fillWidth: true
                    Layout.preferredHeight: 140

                    ColumnLayout {
                        anchors.fill: parent

                        Label {
                            text: qsTr("Card %1").arg(index + 1)
                            font.bold: true
                        }
                        Label {
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                            wrapMode: Text.Wrap
                            text: qsTr("Short description of the card.")
                        }
                    }
                }
            }
        }
    }
}

8. Three-pane workspace

Tools on the left, a work area in the center, and an inspector on the right, with a status bar underneath. This is the typical structure of editors, IDEs, and design tools. It combines the ideas of the previous layouts.

Shown with the Fusion style.

Show the code
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Fusion
import QtQuick.Layouts

ApplicationWindow {
    width: 1100
    height: 700
    minimumWidth: 640
    minimumHeight: 400
    visible: true
    title: qsTr("Three-pane workspace")

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem { text: qsTr("&Open...") }
            MenuItem { text: qsTr("&Quit"); onTriggered: Qt.quit() }
        }
        Menu {
            title: qsTr("&View")
            MenuItem { text: qsTr("Show &inspector"); checkable: true; checked: true }
        }
    }

    footer: ToolBar {
        Label {
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            anchors.leftMargin: 8
            text: qsTr("Ready")
        }
    }

    SplitView {
        anchors.fill: parent

        // Tools
        Pane {
            SplitView.preferredWidth: 200
            SplitView.minimumWidth: 120

            ColumnLayout {
                anchors.fill: parent
                Label { text: qsTr("Tools"); font.bold: true }
                Button { Layout.fillWidth: true; text: qsTr("Select") }
                Button { Layout.fillWidth: true; text: qsTr("Draw") }
                Item { Layout.fillHeight: true }
            }
        }

        // Work area
        Rectangle {
            SplitView.fillWidth: true
            color: palette.base

            Label {
                anchors.centerIn: parent
                text: qsTr("Work area")
                opacity: 0.6
            }
        }

        // Inspector
        Pane {
            SplitView.preferredWidth: 260
            SplitView.minimumWidth: 160

            ColumnLayout {
                anchors.fill: parent
                Label { text: qsTr("Inspector"); font.bold: true }
                TextField { Layout.fillWidth: true; placeholderText: qsTr("Name") }
                CheckBox { text: qsTr("Visible") }
                Item { Layout.fillHeight: true }
            }
        }
    }
}

Where to go next

  • Move repeated parts into their own .qml files and reuse them as components.
  • Replace the placeholder models with a model provided by your backend. See the documentation of your language for how to expose data to QML.
  • Explore the Qt Quick layouts documentation to learn about anchors, alignment, and size policies.
  • For complete applications, see the Qt Quick examples.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.