Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Component.onCompleted in QML: How Does It Work?

Discover how Component.onCompleted fits in QML and why it’s not part of object inheritance. Learn about attached signals and QML architecture.
Visual QML lifecycle diagram showing when Component.onCompleted triggers with glowing effect and attached signal callout Visual QML lifecycle diagram showing when Component.onCompleted triggers with glowing effect and attached signal callout
  • 🔄 Component.onCompleted runs 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 onCompleted handler 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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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 onCompleted in Object.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:

  1. Object Made: The C++ QObject is made.
  2. Properties Set: The engine gives default values, QML values, and basic bindings.
  3. Children Made: Any child items are made, and they go through their own setup steps.
  4. Bindings Checked: Changing values are set.
  5. Signals Connected: JavaScript links like onClicked are made.
  6. Setup Done: Last, Component.onCompleted runs.

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: false or 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 onCompleted for small changes based on what happens.
  • 📣 Use your own ready signals. Separate parts inside other parts from their parents. Then, send a ready() 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 onCompleted calls 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: true links 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.onCompleted is 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 onCompleted runs. 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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading