[Feature Request] Change z-order of widget at runtime

I have an incredibly simple goal of changing the z-order of the buttons as the player scrolls down a menu. Each button as a select animation that changes its scale so they can see which one is selected.

Changing the z-order doesn’t do anything, which makes me wonder why its even a public variable. I’ve found many results suggesting to delete the widget and create it again right away. For me, this doesn’t work because the are children to a sub canvas panel, so when they are created and added again to the canvas their position is set to (0,0).

I tried save the render transform, but there is no way of changing the render transform of a widget, but you can set its position, however, you can’t get the position from another widget. You can, however, get the translation of it, but first of all that’s not nearly the same and its going to change anyways in the animations that I use that change its translation, and second its still doesn’t work, it still appears at (0,0).

This is a very simple feature and I am baffled that this isn’t implemented, and the work around are intuitive and convoluted.

Edit:

Finally got it working. This is what I had to do:

But I find it interesting that this is how you create something that should be just as simple as this:

119293-z-1.png

Of course I’m going to turn this into a function library and call it something like “bring to front,” but this should already come standard and/or have the z-order changeable at runtime.

Terms like “move back, move forward, send to back, bring to forward” are all industry standard terms and are what I would expect to use to do this, so if the feature is here, but called something different, it might as well not be there at all, as searching for this is very hard.

2 Likes

Changing the z-order works, but call
Invalidate Layout and Volatility on the parent of the widget that changed z-order

4 Likes

Could you please create a more in depth explanation of how you did this? I am having trouble following the blueprint you posted.

Worked like a charm! Thanks a million!

I’ve tried Plosnita’s blueprint, but I can’t seem to get it working. Any help?

Hi! That image is from a weird use-case that I have. Don’t take it “as is”.
The image is from the widget that changes it’s Z order when I an not hovering it and I know for sure that it’s parent is a “Canvas”.

What exactly did not work? What is your specific problem and what did you do?

The important things are the " SetZOrder" and “InvalidateLayoutAndVolatility” nodes. Note that they are called upon different objects.

Z order is relevant only for children of the “Canvas” widget. For example a “VerticalBox” does not have a Z order property for it’s children. These children are encapsulated in a “Canvas Slot” type object. For example, if you have a “Text” object, to call “SetZorder”, you still need to get it as a canvas slot (and this is a different object".

So if you want to change the Z order of an object, it has to be inside a “Canvas” (do that from the widget editor), you need to get is as a “canvas slot” by calling “SlotAsCanvasSlot”, use the result from the previous call for the “SetZorder” node.

After that, call “InvalidateLayoutAndVolatility” on the “Canvas” object to let it know something has changed and it’s needs to update.

If you have anymore questions, please ask and give more detailed information.
Also make sure your code gets called (For example “Tick” is not called if a widget is hidden). You can add breakpoints on nodes and the execution will be paused when it reaches that node.

Thank you for the quick reply! I think I see the problem.

The way I have my game set up, the “windows” that I want to change the z-order of are all independent, individual widgets. I’ve set it up so that when opened, each individual “window” widget can be minimized, maximized, and dragged around, but I’m trying to set it up so that when a “window” widget is clicked on, it will be “sent to the front” and overlap all the other windows to allow the user to easily interact with it without having to move everything else out of the way.

I think the problem may be that, since the windows are all different widgets, what you did won’t work for me. Is that correct? Or have you found a way to make one widget overlap another widget once they’re both spawned in the viewport?

It is correct, it would not work directly. I am rearranging widgets withing a widget, while you are trying to rearrange widgets in a viewport. The problem is that I don’t see a method to change the z order or invalidate the viewport and changing it on the widget probably has no effect,

You could try to add your widgets to a master widget that acts as window manager instead of adding them directly to the viewport. This widget would contain only a canvas.

That could work. If you don’t mind, how would I go about doing this?

Looking back, I did put a lot of unnecessary stuff in there.

What I’m doing is:

  1. Save the variables
  2. Remove the widget (delete it)
  3. Create a new widget and add it back to the canvas
  4. Restore the variables
  5. (optional) I replayed the opening animation and called a function on it that I’m supposed to call when creating it.

But don’t use my method, Plosnita’s answer is much more simple and is the way Epic Games intended on us using.

It worked for me. Thanks!

thanks a lot !

Here’s the solution I thought of:
In my game, I switch between HUDs a lot (interactive novel). So I didn’t want to create any blueprint inside the event graph of my HUD or main canvas panel since that would change.


I started by binding to the hover and unhover event in my custom button (I’m using this button: link to unreal forum ).
Also, added an input variable to the binded events (of type Widget - Object reference) to which I plugged in a reference to the Self (right click “Get a reference to self”). (so that I can send that reference to the player controller)

(Note: the next step could be done in the HUD; Gamemode or Player controller) In my case, I don’t have a character so my player controller is what I use for this section. But usually you should be using the HUD.

  • In my case the event is called each time I change the canvas panel on-screen, which is why I clear the array at the beginning.
  • frontZOrder must be > to backZOrder (I put a default value of 30 this way I’m sure nothing else is in front of it.

Lastly, my animation and button effects are still in a separate function. (you don’t need to do this for it to work)

Cheers, hope it helped.