- 🔄
Component.onCompletedruns only once per instantiation after all properties and bindings are set. - 🧩 It is an attached signal. It is not part of the component’s QObject. This lets QML parts work separately.
- 🚀 It's good for actions that happen when a component starts, like making animations begin or sending network requests after loading.
- 🛠️ Every time you make a component, its own
onCompletedhandler runs. This is true even in Repeaters or Loaders. - ⚠️ When people don't understand the signal order or where it works, it often causes problems finding bugs and running logic at the wrong time.
Understanding Component.onCompleted in QML
QML is a language that helps make smooth, quick interfaces using Qt.
People who write QML often have problems with how long a component stays active, especially when things start.
This is where Component.onCompleted comes in. It is a useful but often not understood feature.
When used at the right time, this attached signal gives you exact control after a component is fully made.
It lets you do tasks after setup, start animations, and get data. It does this without getting in the way of what's shown on screen.
What is Component.onCompleted?
Component.onCompleted is an attached signal handler in QML. It is made to run your code just after the QML engine finishes loading and setting up a component.
This happens after all properties, bindings, and child items are checked and set.
Because of this, it is the best place to put code that needs everything to be ready.
Here is a simple example using Component.onCompleted:
Rectangle {
width: 200
height: 100
color: "lightgray"
Component.onCompleted: {
console.log("Component is fully initialized.")
}
}
When this Rectangle is made, the QML engine logs the message. It does this right after setting all properties and finishing setup.
This timing is important. Component.onCompleted helps avoid problems of running code too early when only part of an object is ready.
So, it is an important tool for code that finishes setup.
Not Part of the Object: What Are QML Attached Signal Handlers?
Component.onCompleted is an attached signal. It is not like normal signals such as onClicked on a Button.
This means the engine puts it into your QML objects, instead of it being part of the basic C++ object (QObject).
This difference explains some common problems for developers:
- You will not find
onCompletedinObject.keys(this)inside JavaScript code. - You cannot call or link to it using JavaScript or C++ code.
- It is set up when QML code is read, not when the QObject is made.
Attached signals work with QML's special type system. This lets signals work for specific situations without making the QObject system more complex.
Other QML attached signals are Keys.onPressed, FocusScope, and Layout properties. These all seem to be "part" of an object but keep things separate on purpose.
Execution Sequence and Runtime Behavior
The QML engine follows a set order when starting any component.
Putting Component.onCompleted in this process makes sure your code runs after all properties and bindings are stable.
Here is the standard order:
- Object Made: The C++ QObject is made.
- Properties Set: The engine gives default values, QML values, and basic bindings.
- Children Made: Any child items are made, and they go through their own setup steps.
- Bindings Checked: Changing values are set.
- Signals Connected: JavaScript links like
onClickedare made. - Setup Done: Last,
Component.onCompletedruns.
This sixth and last step makes sure your code will not get in the way or be changed unexpectedly by other parts of the setup.
This gives much more steady results, especially when working on things users see or animations that start after loading.
Component.onCompleted in the Component Lifecycle
Component.onCompleted plays an important part no matter how a component loads. This means whether it's put directly in the code, loaded later, loaded as needed, or made many times.
Static Loading
Static components are written right there in the code:
Rectangle {
width: 300
height: 200
Text {
id: greetingText
text: "Welcome"
Component.onCompleted: {
console.log("Greeting Text is ready with width:", greetingText.width);
}
}
}
Here, onCompleted helps us do layout work or size changes once the element is shown with the right size.
Loading Later or As Needed
With Loader, objects are not made until the program runs. Component.onCompleted helps handle UI code at those times.
Loader {
id: deferredLoader
sourceComponent: cardComponent
}
Component {
id: cardComponent
Rectangle {
width: 100
height: 100
color: "skyblue"
Component.onCompleted: {
console.log("Card component loaded at runtime.")
}
}
}
Components might load with delay. Because of this, this handler becomes very important for making UI parts work together, starting fade-in effects, or telling other parts of the system that components are on screen.
Common Misunderstandings and Times When You Need to Fix Errors
Many bugs with Component.onCompleted happen because people do not understand what it is or where it works.
Common issues include:
- 🔍 Thinking it's a QObject method and failing to look at or use it with code.
- 🕵️♂️ Fixing errors in complex UI designs and not knowing why some code meant to run after setup does not start.
- 📦 Thinking components used many times will act the same in all loading situations, which is not always true.
Here is what you can do to fix errors:
- Use
console.log("onCompleted fired")right inside the handler to make sure it runs. - Double-check if your component was actually made. Sometimes Loaders do not start or QML files are not found.
- Check you have not stopped it from being made with
visible: falseor other code that makes it wait.
The QML profiler or Qt Creator's own tools can help show when and how each onCompleted signal runs in places with many parts inside each other or many copies.
When to Use Component.onCompleted
This signal is made for times when code should only run after a component is fully ready:
- ✅ Starting actions: Make calls to the server like
api.fetch()when the UI is shown. - ✅ Fixing layout: Change element positions based on their set sizes.
- ✅ Starting changes: Use visual effects or animations that begin when the UI shows.
- ✅ Keeping states in sync: Tell other parts (like analytics) that the page is on screen.
Example:
Component.onCompleted: {
fadeIn.start();
userStats.fetchLatest();
console.log("MainScreen is ready for people to use.");
}
Best Practices
Use these guidelines for good and safe Component.onCompleted use:
- 🧼 Keep code simple. Do not use timestamps, delays, or repeating calls.
- 📐 Avoid changes to how things are built. Make layouts ahead of time. Use
onCompletedfor small changes based on what happens. - 📣 Use your own
readysignals. Separate parts inside other parts from their parents. Then, send aready()signal after all setup code runs.
Example of making parts ready in a good way:
MyComponent {
id: module
onReady: {
dashboard.loadWidgets();
}
}
Inside MyComponent:
Signal ready
Component.onCompleted: {
console.log("MyComponent initialized.");
ready();
}
This way keeps code clear and able to be put together. This is a main idea in QML.
Problems to Avoid
Even skilled developers can hit known problems if they use onCompleted too much.
- 🔁 Order surprises: Child parts might be ready before parent parts, messing up what you expect.
- 🔀 Bad code links: Do not use it as the main point to make things happen at the same time, unless you plan it out exactly.
- 🌀 Using it too much in builds that change: Many
onCompletedcalls in repeaters can cause too much setup work at once.
Example of a wrong idea:
ParentItem {
Component.onCompleted: {
child.initNow(); // ❌ May be undefined
}
ChildItem {
id: child
Component.onCompleted: {
console.log("Child item ready");
}
}
}
Solution: Make sure everything is ready at the parent level only when all parts send ready() signals.
Many Calls for Reused Components
Using parts again is good, but setup signals can surprise you.
Component {
id: reusableBox
Rectangle {
width: 50; height: 50
color: "coral"
Component.onCompleted: console.log("Box set up")
}
}
Repeater {
model: 4
delegate: reusableBox
}
Each of the 4 boxes will run its own finish signal. This is normal.
But it means your code should handle each part being ready on its own. Do not think they all finish at the same time.
When you need a group effect (like a planned animation), think about gathering these finish states using a signal counter.
onCompleted vs Separate Setup Functions
You may want to put all your setup code in onCompleted, but that is not always the best way.
Look at these two ways.
A single way to handle each object:
Component.onCompleted: initLogic()
Vs. setup directly from parent:
Component.onCompleted: {
column.children.forEach(obj => {
if (obj.initLogic !== undefined)
obj.initLogic();
});
}
Pick based on how complex your app is.
For a clear, separate design, let child parts do their own setup. And then, let the parent control big tasks.
Fixing Errors in onCompleted Calls
Still not seeing what you expect?
- 👁 Use
visible: truelinks and property watchers to check what is shown on screen. - 🔎 Use
Qt.createQmlObject()with code around it to follow when objects are made. - 📋 Put
console.log(component)with extra info to see when and where signals run.
Example:
Component.onCompleted: {
console.log("Component ready at", new Date().toLocaleString());
}
This shows it runs. It also shows time differences in places that load a lot.
Example from Real Apps: App Startup
Real QML apps often use Component.onCompleted to make screen changes or login steps work together.
ApplicationWindow {
visible: true
width: 800
height: 600
ApiClient {
id: api
}
Component.onCompleted: {
console.log("App window set up");
api.login();
mainContent.source = "Dashboard.qml";
}
Loader {
id: mainContent
}
}
Here, logging in starts only after the ApplicationWindow finishes loading and links with its properties.
Not letting things start at the same time during partial loading keeps the app working well.
Features Side-by-Side
| Feature | When it runs | What it's used for |
|---|---|---|
Component.onCompleted |
After all component setup | Setup code after loading |
onVisibleChanged |
When it becomes seen or not seen | Show/hide animations or tracking |
onWidthChanged |
When width changes | UIs that change with size |
Custom init() function |
Started by hand | Making objects under specific control or conditions |
Component.onDestruction |
When it is removed | Code to clean up before memory is freed |
Each handler or function works at a certain time in a component's life. Use onCompleted as a safe, steady point after everything is set up.
Main Points
- ✅
Component.onCompletedis a special attached signal in QML for running code after an object is fully made. - 🧠 It is different from other signals because it is part of the QML engine, not the QObject itself.
- 🔁 Every time a component is made, its own
onCompletedruns. This is extra important when using Repeater and Loader. - ⚙️ It is best used for setup steps after showing things, like animations, server updates, or sending "ready" signals.
- 🔧 Keep its code small and simple, design parts to work alone, and do not use it as your only way to make things happen at the same time.
By understanding the small details of Component.onCompleted and related signals, developers can make user experiences smoother. They can also get better control over the loading order and build simpler ways to set things up.
References:
Qt Company. (n.d.). Qt QML Signals and Handlers. Qt Documentation.
Qt Company. (n.d.). QML Component Lifecycle. Qt Documentation.