When to use
Use this when you are structuring a Qt Quick UI from requirements — choosing layout containers, wiring a theme, making it responsive across window sizes, and keeping it accessible — rather than transcribing a specific design file.
Not for: pulling tokens out of a Figma file (see qt-figma-token-extraction) or code-generating components from Figma frames (see qt-figma-component-generation).
Method
- Establish the theme first: create a
Theme.qmlsingleton (pragma Singleton) for colors, spacing, radii, and fonts so every screen references tokens, not literals. - Pick the control layer. Decision point: if you want a platform look-and-feel and built-in accessibility, use Qt Quick Controls 2 with a style (
Material/Universal/Fusion/Basic); if you need fully bespoke visuals, composeItem/RectanglewithMouseArea/TapHandler. - Choose the positioning system per container. Decision point: if children must flow/stretch/share space, use
RowLayout/ColumnLayout/GridLayoutwithLayout.*attached properties; if a child is pinned relative to its parent or a sibling, useanchors. Never apply both to the same item. - Set the base element. Decision point: if an element only needs geometry/clipping/opacity, use
Item; if it needs a fill, border, or radius, useRectangle. - Make it responsive: drive size with
Layout.fillWidth/Layout.fillHeight,Layout.preferredWidth, andLayout.minimumWidth; switch structure at breakpoints viastatesbound to the window/root width. - Define
statesandtransitionsfor interactive and adaptive changes so geometry and visibility animate instead of snapping. - Handle high-DPI by working in logical pixels only — Qt 6 scales by the screen device pixel ratio automatically; provide
@2x/SVG assets rather than manual multipliers. - Add accessibility: attach
Accessible.role/Accessible.nameto custom interactive items; Controls provide these by default. Decision point: if an item is custom-drawn and clickable, it must carry anAccessiblerole, otherwise screen readers skip it. - Verify by resizing the window and running with a screen reader /
Accessibleinspection before considering the layout done.
Example
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import MyApp.Theme
ApplicationWindow {
id: root
visible: true
width: 900; height: 600
readonly property bool compact: width < 600
ColumnLayout {
anchors.fill: parent
anchors.margins: Theme.spacingMd
spacing: Theme.spacingSm
Label {
text: qsTr("Dashboard")
font: Theme.titleLarge
color: Theme.colorOnSurface
Layout.fillWidth: true
}
GridLayout {
Layout.fillWidth: true
Layout.fillHeight: true
columns: root.compact ? 1 : 3 // responsive breakpoint
columnSpacing: Theme.spacingMd
rowSpacing: Theme.spacingMd
Repeater {
model: 6
delegate: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 120
radius: Theme.radiusLg
color: Theme.colorSurface
Accessible.role: Accessible.Button
Accessible.name: qsTr("Card %1").arg(index + 1)
TapHandler { onTapped: console.log("card", index) }
}
}
}
}
}
Pitfalls
- Mixing anchors and Layout. Setting
anchors.*andLayout.*on the same item produces conflicting geometry and runtime warnings. Choose one system per item. - Hardcoded pixel sizes. Fixed
width/heighteverywhere breaks responsiveness and high-DPI. PreferLayout.fillWidth/preferredWidthand content-drivenimplicit*. - Manual DPI math. Multiplying sizes by a scale factor double-scales against Qt 6's automatic DPR handling. Stay in logical pixels.
- Styling Controls by editing internals. Overwriting
contentItem/backgroundper instance instead of using a style is unmaintainable; set the style once and theme via the singleton. - Missing accessibility on custom items. Bespoke
Rectangle+handler widgets are invisible to assistive tech without anAccessible.role/name. - Non-animated state changes. Toggling geometry/visibility without
transitionsmakes responsive reflows jump; pairstateswithTransition/Behavior.
Output format
main.qml # ApplicationWindow root, layout skeleton
Theme.qml # pragma Singleton design tokens
components/*.qml # reusable, property-driven UI pieces
qtquickcontrols2.conf # selected Controls style + palette (optional)
// screen skeleton
ApplicationWindow {
// root breakpoint props (e.g. compact: width < 600)
ColumnLayout { // or Row/GridLayout
anchors.fill: parent // anchors on the top container only
spacing: Theme.spacingSm
// children use Layout.* for sizing, Theme.* for style,
// Accessible.* on custom interactive items,
// states + transitions for responsive/interaction changes
}
}
Reference
- Qt Quick Layouts (
import QtQuick.Layouts):RowLayout,ColumnLayout,GridLayout. Attached properties on children:Layout.fillWidth/Layout.fillHeight(bool),Layout.preferredWidth/Layout.preferredHeight,Layout.minimumWidth/Layout.maximumWidth,Layout.alignment(e.g.Qt.AlignHCenter | Qt.AlignVCenter),Layout.margins,Layout.columnSpan/Layout.rowSpan. - Anchors vs Layouts: anchors (
anchors.fill,anchors.centerIn,left/right/top/bottom,margins) andLayout.*must not be combined on the same item. Anchor the outermost container to its parent; use Layouts for children. - Qt Quick Controls 2 styling: styles are
Basic,Fusion,Material,Universal(alsomacOS/Windowsnative on Qt 6). Select at runtime withQQuickStyle::setStyle("Material")in C++ before loading QML, via theqtquickcontrols2.conffile ([Controls] Style=Material, plus[Material]palette keys), or theQT_QUICK_CONTROLS_STYLEenv var. Style attached props likeMaterial.theme/Material.accentcustomize per subtree. - Theme singleton:
pragma SingletonQtObjectregistered viaqt_add_qml_module+QT_QML_SINGLETON_TYPE; reference asTheme.<token>. Keep colors/spacing/typography here (see qt-figma-token-extraction for populating it). - High-DPI: Qt 6 enables high-DPI scaling by default and works in logical/device-independent pixels; the app scales by each screen's
Screen.devicePixelRatio. Ship@2xraster variants or SVG; avoid manual scale factors andpointSizeguesswork (preferpixelSize). - Item vs Rectangle:
Itemis the base visual type (no painting) for grouping, geometry, clipping (clip), and opacity;Rectangleaddscolor,border.color/border.width,radius, and gradients. UseItemunless a fill/border is needed. - States & transitions:
states: [ State { name; PropertyChanges { target; ... } } ]withtransitions: [ Transition { NumberAnimation/PropertyAnimation } ];Behavior on <prop>animates individual property changes. Drive responsive layout by binding containercolumns/visibility/state to root width breakpoints. - Accessibility: the
Accessibleattached property exposes items to assistive tech —Accessible.role(e.g.Accessible.Button,Accessible.StaticText,Accessible.CheckBox),Accessible.name,Accessible.description,Accessible.focusable,Accessible.onPressAction. Qt Quick Controls set sensible defaults; custom interactive items must set them explicitly. Wrap user-facing strings inqsTr(...)for i18n.