Image showing a popup window being centered in a laptop screen

QML mapToItem vs mapToGlobal—When and How to Use Each

QML popup centering Mar 7, 2025

When working with QML, you often need to position UI elements relative to a global or local coordinate system. To contextualize it, imagine you have your layout done with a sidebar on the left and the main context view taking over the remaining space.

App layout (sidebar, toolbar, main content area)

Inside the main view, you need to spawn a popup that displays some information or even get user input for processing. A simple way to center your popup would be to manipulate the items `x` and `y` coordinate systems as shown below;

// Other QML imports here

Popup {
	width: 300
	height: 250
	
	// `app` here is the ID for the root window
	x: (app.width - width)/2
	y: (app.height - height)/2
}

As expected, the popup when opened is centered on both the horizontal and vertical axes of the parent view. On closer look, we can see the popups x-offset is larger on the left than on the right side of the popup. The screenshot below shows the effect of adding spacing in a RowLayout containing the SideBar and the MainContentItem. But why isn't the popup centered?

App screenshot showing popup being off-center

Remember that the popup centering by setting the x and y value is relative to the parent Item. In this case, we are creating the popup from within the MainContentItem. As such, the calculated x value is does not take into account the presence of the SideBar as well as the RowLayout spacing; hence, the spawned popup is off-center but spacing + sidebar width.

Quick Fix

A common approach I have seen on other codebases (including how I used to do it) is to use the mapToGlobal function to get the global coordinates and calculate the x and y offsets from it. In theory, this approach is correct; however, I've observed several novice errors, including my own. So, a quick solution for the xOffset would be;

// Other code as before
x: (app.width - width)/2 - ((app.width - width)/2 - mapToGlobal(0,0).x)
// Other code as before

What's all that mumbo jumbo? Basically, we are:

  • Calculating the x center from the parent item using (app.width - width)/2
  • We are calculating the difference between the mapped x-position of the (0,0) position of our popup and the global position and the x-center above. This, in theory, should give the offset to apply on the x-side to reposition the popup.
  • Lastly, we subtract the offset from the x-center in step 1. In theory, this should center the popup in the window.

But, looking at the output window, our popup is way off-center. It was even better before, kind of; we have made it worse. Where did we go wrong?

Popup position after the quick fix

Understanding mapToGlobal vs mapToItem

First, when an app draws its window, there are two coordinate systems at play here. One is the global coordinate relative to the monitor or screen. The next is the local coordinate relative to the app's top-left position, a.k.a., the origin (0,0) or the parent item.

For mapToGlobal, it converts the given local coordinate into a global screen coordinate. That is, whether the app is full-screen, maximized, or just taking a small portion, the coordinate returned is relative to the screen and not the window/app in question.

In contrast, mapToItem takes a target item as the first parameter and the coordinates to transform as the second and third parameters. This maps the current item's coordinate position to the item of interest.

How do we fix our `perfect` popup centering?

Quite simple now that we understand the concepts above. Let's map the popup’s origin position to the ApplicationWindow's contentItem to the x & y offsets. The returned offset x and y shall be subtracted from our x-center and y-center, respectively.

// Other code as before
x: (app.width - width)/2 - mapToItem(app.contentItem, 0,0).x
// Other code as before

As noted, `mapToItem` expects an item as a parameter. Our Window or ApplicationWindow is not an item and will throw an error if passed in. To resolve that, access the item within the window, which is usually the `contentItem`.

Conclusion

A similar approach can be used to apply the offset on the y-axis. I hope you found this informative; let me know how you would have done the alignment.

Cheers!

Tags