It appears as though the Construct event for a widget is being fired every time the widget is added to the viewport, not just once when it is constructed. Is this a bug, or is this intentional? It seems like it would be useful to have both: an actual Construct event that is fired once when the widget is created, and a separate event that is fired every time it is added to the viewport.
Hello BaronPumpky,
This is not a bug and the engine is working as intended. However, I have submitted a feature request to the development team. Thank you for your input. Request # UE-4706
Make it a great day.
Do you have any Information about the state of this request, like if it was accepted or rejected?
Hello ,
I went ahead and double checked for you. It appears that this feature request is still under consideration by the developers. However, you could achieve this result by having two widgets blueprints. A “Master widget” blueprint and a the widget blueprint that you would like added to the viewport.
To achieve the “One time Construction”, you would use the Master widget’s construction event (This is added to the screen once and left there). NOTE: This is the widget blueprint that you will use the “Add to Viewport” node on.
To achieve the “Construction on add to viewport”, you would use the Widget blueprint that you would like add to the screen’s construction event. However, instead of adding it to viewport, you would simply add it as a child to the Master blueprint and then remove it from parent as normal to remove it from the viewport.
I hope that this information helps.
Make it a great day
Thank you very much, for your research and interesting approach to bypass this behavior.
Hi Rudy.
Since you say this is intended behaviour, I wonder if you could explain what is wrong with my usage that is causing an assertion failure.
I have a UUserWidget-derived class, within which I have a few UPROPERTY references to embedded widget components, for example:
UPROPERTY(EditAnywhere)
class UComboBoxString* Box1;
I assign these properties in my widget’s blueprint construction event (with the variables from the components added in the designer), before invoking the Parent: Construct node.
Then in the c++ Construct_Implementation, I set up delegates on these widget components. When I add my user widget to a viewport, remove it, then add it a second time, I get an assertion failure within AddDynamic:
check( InvocationList[ CurFunctionIndex ] != InDelegate );
It appears that although the user widget is getting reconstructed, the embedded widget components persist, and as such I get the error from trying to bind the same method to the delegate a second time. Clearly there is an issue with this process, can you explain what is wrong with my approach? Thanks.
Hello ,
I was unable to reproduce this issue on our end. I have a few questions to help narrow down what issue it is that you are experiencing. I have also included a working example of what was described in my last post. I hope that this helps.
Quick questions:
- What version of the engine are you using?
- Can you reproduce this issue in a clean project?
- Is so, could you provide a detailed list of steps to reproduce this issue on our end?
- Could you provide screen shots of any blueprints or code that you may be using.
Example:
Master widget blueprint:
The master widget starts out empty except for a button that I will use to toggle the Child widget on and off (in this case the child widget is named “ActionWidget”).
Action Widget:
This is an image that is added and removed by the master widget.
Level Blueprint:
I have added the master widget to the viewport.
Make it a great day
Hi Rudy. I’m using 4.7.6.
To reproduce simply do the following:
-
Add a new c++ class deriving from UUserWidget, as follows:
// TestUserWidget.h
#pragma once#include “Blueprint/UserWidget.h”
#include “TestUserWidget.generated.h”UCLASS()
class AWARENESSDEMO_API UTestUserWidget : public UUserWidget
{
GENERATED_BODY()public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UButton* TestButtonProp;virtual void Construct_Implementation() override; UFUNCTION() void OnClicked();
};
// TestUserWidget.cpp
#include “ProjectPCH.h”
#include “TestUserWidget.h”
#include “Components/PanelWidget.h”
#include “Components/ContentWidget.h”
#include “Components/Button.h”void UTestUserWidget::Construct_Implementation()
{
TestButtonProp->OnClicked.AddDynamic(this, &UTestUserWidget::OnClicked);
}void UTestUserWidget::OnClicked()
{}
-
In the editor, add a new Widget Blueprint, and reparent it to the above class.
-
Drop a button (named TestButton) in the designer, then configure the event graph as shown.
- In level blueprint BeginPlay (or anywhere really) create an instance of the widget, and immediately call in succession: AddToViewport → Remove → Add.
Note that I can easily find ways to work around the resulting crash, but I’d just like to know what it is about the process that is incorrect usage. Specifically, it seems counter intuitive to me that the parent user widget could get reconstructed while its child components persist.
Cheers.
Hello ,
The issue that you have reported was unrelated to the original issue, however after testing out the reproduction steps that were provided we found that there was an issue. This issue has been reported and will be under further consideration by the developers. The issue occurs specifically with a C++ version of the widget that you made. If you were to remake this widget in blueprints it should work fine. If you are trying to do straight C++ UI elements then extending UWidget , the base widget class, or making something directly in Slate could be a better way to go about it. I hope that this information helps.
Make it a great day
Okay, thanks for following up on this.
The reason for my approach is that I wanted to be able to create composite widgets using the benefits of the designer, yet implement the logic of the interactions in c++. Hence assigning the child widget references in the blueprint construct event.
Anyway, as I said, I have no problem working around this for now. If an update could be posted here if a fix is made, that would be great.
Cheers.
I confirm this problem. NativeConstruct called each time, when I’m calling Widget->AddToViewport. And if you have something like this in it:
Button->OnClicked.AddDynamic(this, &UMyClass::OnCloseButtonClick);
then you will get an error.
And this is still happening in version 4.16.2 … just saying…
Do you have any information about the state of this request ?
I have a similar behavior, everytime I’m calling AddToScreen node in blueprint, the NativeConstruct C++ function is called. I’m using UE4.19.2.
I’m working on a widget managing the player inventory. The widget is AddToScreen when we want to show the inventory and then RemoveFromParent when we want to close it. We are doing that for all the menus but the inventory menu in particular is taking a long time.
Another thing is that the RemoveFromParent node will call the NativeDestruct C++ function everytime.
I would like to be able to call the NativeConstruct only one time, and then adding or removing the widget to the screen.
Do you have any advice on how I can achieve that ?
I’ve tried using a Master widget as suggested above, but it doesn’t solve my issue because AddChild node will call the NativeConstruct C++ function of my widget everytime.
I’m currently reworking this widget to use AddToScreen only one time and then set its visibility to Colapsed or Visible but this solution is far from perfect.
If it hasn’t been mentioned, you can use On Initialized, which runs just once on a User Widget.