Download

Widget with runtime content not showing visual modifications..,

I am trying to create a set of widgets that behaviors like a popup window. First one is UPopupWindow, which implements base behavior:

HEADER



#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Border.h"
#include "HexUIButton.h"

#include "PopupWindow.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPopupWindowEvent, UWidget*, contentWidget);

/**
*
*/
UCLASS()
class TCWMOBILE_API UPopupWindow : public UUserWidget
{
GENERATED_BODY()
public:
UPopupWindow(const FObjectInitializer& ObjectInitializer);

protected:
void NativeDestruct() override;

UFUNCTION()
virtual void DisplayPopupWindow(UWidget* contentWidget);
UFUNCTION()
virtual void OnCloseButtonClickedInternal();

private:
FScriptDelegate OnCloseWindowClicked;

public:
UPROPERTY(BlueprintCallable, Category = "Events")
FPopupWindowEvent OnDisplayPopupWindow;

UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
UHexUIButton* CloseWindowButton;

UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidgetAnim))
UWidgetAnimation* DisplaySelf;

UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
UBorder* ContentBorder;
};


CPP


// Copyrigth (c) 2020 Softwar 19.23 NGS. All rigths reserved.

#include "PopupWindow.h"
#include "MiscFunctionLibrary.h"

UPopupWindow::UPopupWindow(const FObjectInitializer& ObjectInitializer) : UUserWidget(ObjectInitializer)
{
OnDisplayPopupWindow.AddDynamic(this, &UPopupWindow::DisplayPopupWindow);
OnCloseWindowClicked.BindUFunction(this, "OnCloseButtonClickedInternal");
}

void UPopupWindow::NativeDestruct()
{
ContentBorder->ClearChildren();
CloseWindowButton->OnClicked.Remove(OnCloseWindowClicked);
}

void UPopupWindow::DisplayPopupWindow(UWidget* contentWidget)
{
CloseWindowButton->OnClicked.AddUnique(OnCloseWindowClicked);

if (contentWidget->IsValidLowLevel())
{
ContentBorder->AddChild(contentWidget);
}
PlayAnimation(DisplaySelf);
}

void UPopupWindow::OnCloseButtonClickedInternal()
{
PlayAnimation(DisplaySelf, 0.0f, 1, EUMGSequencePlayMode::Reverse, 1.0f, false);

RemoveFromParent();

this->Destruct();
}


And there is another widget UDialogWindow that inherits from that one, here’s cpp relevant section.



UDialogWindow::UDialogWindow(const FObjectInitializer& ObjectInitializer) :
UPopupWindow(ObjectInitializer)
{
ConstructorHelpers::FObjectFinder<UTexture2D> tickIcon(TEXT("Texture2D'/Game/Textures/UserInterface/TCW_TickIcon.TCW_TickIcon'"));
if (tickIcon.Succeeded())
{
acceptButonIconTexture = tickIcon.Object;
okButonIconTexture = tickIcon.Object;
yesButonIconTexture = tickIcon.Object;
}
ConstructorHelpers::FObjectFinder<UTexture2D> crossIcon(TEXT("Texture2D'/Game/Textures/UserInterface/TCW_CrossIcon.TCW_CrossIcon'"));
if (tickIcon.Succeeded())
{
cancelButonIconTexture = crossIcon.Object;
noButonIconTexture = crossIcon.Object;
}

OnShowDialog.BindDynamic(this, &UDialogWindow::ShowDialog);
}

void UDialogWindow::ShowDialog(FDialogButtonsButtons buttons, FText message)
{
buttonsEnum = buttons;
responseEnum = FDialogWindowResponse::DialogWindow_Unknown;

switch (buttonsEnum)
{
...
case FDialogButtonsButtons::DialogButtons_YesNo:
{
LeftButton->IconTexture = yesButonIconTexture;
LeftButton->OnClicked.AddDynamic(this, &UDialogWindow::OnAcceptButtonClickedInternal);
LeftButton->SetToolTipText(TextYes);
RightButton->IconTexture = noButonIconTexture;
RightButton->OnClicked.AddDynamic(this, &UDialogWindow::OnCancelButtonClickedInternal);
RightButton->SetToolTipText(TextNo);
LeftButton->SetVisibility(ESlateVisibility::Visible);
break;
}
...
}

UTextBlock* content = WidgetTree->ConstructWidget<UTextBlock>();// CreateWidget<UTextBlock>(this);
content->SetText(message);
content->StaticRegisterNativesUObject();
Super::DisplayPopupWindow(content);
}


In fact, logic is working fine, the dialog is displaying and the events are bound correctly, also return event works in blueprint, sending dialog result back.

My problem is just here:



UTextBlock* content = WidgetTree->ConstructWidget<UTextBlock>();
content->SetText(message);
content->StaticRegisterNativesUObject();
Super::DisplayPopupWindow(content);


and here:



void UPopupWindow::DisplayPopupWindow(UWidget* contentWidget)
{
CloseWindowButton->OnClicked.AddUnique(OnCloseWindowClicked);

if (contentWidget->IsValidLowLevel())
{
ContentBorder->AddChild(contentWidget);
}
PlayAnimation(DisplaySelf);
}


contentWidget is not showing inside the parent widget, nor updating button textures.

If I had to guess – and mind you, this is merely a guess, so take it for what it’s worth – your


UTextBlock* content 

might be getting garbage collected before it ever makes it to your if check (or have you verified that


ContentBorder->AddChild(contentWidget);

actually gets called? – does the if check fail?). If it is the GC, you may want to consider having that pointer be declared as a property of the UPopupWindow class. That way, since the pointer belongs to an object instead of being declared in the middle of a function, the GC should leave it alone. Again, just a guess. I look to others that may know better to chime in.