This article focuses on two of the most common UI capabilities in Qt Quick: QML ListView rendering and custom TextField inputs. It addresses the fragmented understanding many beginners have around model, delegate, ListModel, anchors, and style customization, then connects these core concepts through runnable examples. Keywords: QML ListView, TextField, custom components.
Technical Specification Snapshot
| Parameter | Description |
|---|---|
| Language | QML |
| Framework | Qt Quick / Qt Quick Controls |
| License | Not explicitly stated in the original article; the page displays CC 4.0 BY-SA |
| GitHub Stars | Not provided in the original article |
| Core Dependencies | QtQuick 2.12, QtQuick.Window 2.2, QtQuick.Controls 2.5, QtQml 2.0 |
This note actually covers two high-frequency QML scenarios
The first part explains the ListView list component, with a focus on the difference between a numeric model and a custom ListModel, as well as how delegate determines the rendering of each item.
The second part covers a custom TextField, focusing on anchor-based layout, padding, background replacement, embedded icons, and the onTextChanged signal. Together, these two capabilities are enough to support most basic Qt Quick interface prototypes.
The core of ListView is a data-driven view
In QML, ListView itself does not care what your business data looks like. It only depends on model to provide data, and then uses delegate to describe how each data item should be displayed. As a result, the key to understanding lists is not the control’s appearance, but the data binding path.
ListView {
width: 100
height: 100
anchors.centerIn: parent // Center the list in the parent container
spacing: 10 // Set spacing between list items
model: 10 // Generate 10 items with values from 0 to 9
delegate: Label {
text: "The number is: " + modelData // modelData represents the current item value
color: "#fff"
font.pointSize: 14
}
}
This code quickly generates a numeric list and works well for validating the minimum viable ListView + delegate pattern.
Using a fixed numeric model helps you quickly understand modelData
When model: 10 is used, QML automatically creates 10 anonymous data items with indexes ranging from 0-9. This type of model is ideal for teaching and debugging because it does not require you to declare an additional data structure.
The most important variable here is modelData. It is the default entry point inside the delegate for accessing the current item’s data. In a simple model, it directly represents the number itself. In an object-based model, you typically access named fields instead.
A custom ListModel is closer to real project data
In real projects, you usually do not display a single number. Instead, you display structured fields such as name, age, status, or avatar. In that case, you should use ListModel together with multiple ListElement objects to build an explicit data source.
ListModel {
id: mymodel
ListElement { name: "ycc"; age: 24 }
ListElement { name: "yc"; age: 27 }
ListElement { name: "yccd"; age: 29 }
ListElement { name: "ycfc"; age: 28 }
ListElement { name: "ydcc"; age: 20 }
}
This code defines a structured list model in which each ListElement is a data record that a view can consume.
Decoupling the model from the delegate significantly improves reusability
As the data structure becomes more complex, you should avoid inlining a large block of UI directly inside delegate. A more maintainable approach is to encapsulate the list item in a separate Component and then reference it from ListView.
ListView {
width: 100
height: 100
spacing: 10
anchors.centerIn: parent // Center the entire list
model: mymodel // Bind the custom model
delegate: mydelegate // Use an external component as the delegate
}
Component {
id: mydelegate
Label {
text: "Name: " + name + " Age: " + age // Read model fields directly
color: "#fff"
font.pointSize: 14
}
}
This example shows the standard ListModel + ListView + Component combination, which is suitable for small and medium-sized business lists.
The key to a custom TextField is not input itself, but style overriding
TextField works out of the box, but in real interfaces you usually need to customize the background, icons, and padding. The strength of QML is that you can directly rewrite control styling through declarative composition instead of relying on complex inheritance.
import QtQuick 2.12
import QtQuick.Window 2.2
import QtQuick.Controls 2.5
ApplicationWindow {
visible: true
width: 1000
height: 700
title: qsTr("Application Demo")
Rectangle {
anchors.fill: parent
color: "orange"
TextField {
anchors.centerIn: parent // Place the input field in the center of the window
width: 200
color: "red"
font.pointSize: 24
topPadding: 15
bottomPadding: 15
leftPadding: 70 // Reserve space for the left icon
rightPadding: 20
background: Rectangle {
anchors.fill: parent
color: "yellow"
radius: 7 // Draw a rounded background
}
Image {
source: "qrc:/images/photo.png"
width: 32
height: 40
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
onTextChanged: {
console.log("Text Change") // Print a debug log when the text changes
}
}
}
}
This code creates a custom input field with a left-side icon, a rounded background, and input change monitoring.
Anchor-based layout and padding together determine control usability
anchors.centerIn determines where a control is placed, while padding determines whether its content feels comfortable to use. Many input fields look functional but feel awkward in practice, and the root cause is often not the control itself, but the lack of enough space for text and icons.
In this example, leftPadding: 70 is the key line. Without it, the input text would overlap with the image on the left, reducing readability. Meanwhile, background replaces the default skin so the TextField can have its own visual style.
The original image is primarily decorative and does not carry core technical information
![]()
AI Visual Insight: This image is a “Run Code” entry icon used mainly for page interaction cues. It does not show the QML component tree, layout hierarchy, or runtime UI result, so it does not provide meaningful technical structure information.
These two examples reveal a unified learning path
Start with anchors and basic controls, then learn model/delegate, and finally move on to component encapsulation and style overriding. This is the most reliable path for Qt Quick beginners because it follows the cognitive sequence of layout first, data second, and abstraction third.
If you want to go deeper, the next topics to study should be Repeater, GridView, property binding, state machines, and the qrc resource system. That is how you move from writing demos to building practical interfaces.
During development, remove redundant imports and leftover comments first
The original code includes repeated QtQuick imports across versions and an unused Material module. For beginners, this kind of redundancy may not trigger immediate errors, but it increases cognitive load and can easily create confusion around versioning.
import QtQuick 2.12
import QtQuick.Window 2.2
import QtQuick.Controls 2.5
import QtQml 2.0
// Remove duplicate or unused modules to keep dependencies minimal
This example shows that QML dependency declarations should remain as minimal as possible to reduce maintenance cost and ambiguity.
FAQ
Q1: What are the responsibilities of ListView, model, and delegate?
ListView is the container responsible for scrolling and holding the list. model provides the data. delegate determines how each item is rendered. Without any one of these three parts, the list cannot work correctly.
Q2: When should you use modelData, and when should you use fields like name and age directly?
Use modelData when the model is a simple value such as model: 10. Use explicit field names such as name and age directly inside the delegate when the model is a ListModel with named fields.
Q3: Why do you need to set leftPadding when customizing an input field?
Because an Image icon is embedded on the left side. If you do not increase the left padding, the text will overlap the icon area. In essence, leftPadding redraws a safe boundary for the content area.
Core Summary: This article restructures a Qt Quick/QML study note around two high-frequency interface capabilities: the ListView list component and the custom TextField input field. It covers model, delegate, ListModel, Component, anchors, padding, background, Image, and signal handling, while also providing runnable examples, a structured summary, and frequently asked questions.