Keywords: UE4, Native UMG, Slate, Common API, Usage, Case

Native UMG APIs In Common

How to set UButton’s Image Texture for Normal, Hovered and Pressed state
MyButton->WidgetStyle.Normal.SetResourceObject(TextureRes);
How to get the size of widget

Get actual size of widget:

FVector2D UWidget::GetDesiredSize() const

Usage of GetDesiredSize:

void UMyWidget::AddToScreen(ULocalPlayer* LocalPlayer, int32 ZOrder)
{
    Super::AddToScreen(LocalPlayer, ZOrder);

    Super::ForceLayoutPrepass();

    FVector2D Size = GetDesiredSize();
}

GetDesiredSize() isn’t usable before NativeTick() triggered, if you want to get the widget size when widget initilized, you need to call function Super::ForceLayoutPrepass(). If you add a child in widget and want to show it on viewport at this frame, you also need to call this function too.

Get size using slot:

//ImgIcon is a UImage widget.
if (UCanvasPanelSlot* Slot = Cast<UCanvasPanelSlot>(ImgIcon->Slot))
{
    FVector2D Size = Slot->GetSize();
}

Get size from Texture2D resource:

//ImgIcon is a UImage widget.
if (UTexture2D* Tex = Cast<UTexture2D>(ImgIcon->Brush.GetResourceObject()))
{
    int32 X = Tex->GetSizeX();
}

Using CachedGeometry:

const FVector2D& IconLocSize = ImgIcon->GetCachedGeometry().GetLocalSize();
const FVector2D& IconAbsSize = ImgIcon->GetCachedGeometry().GetAbsoluteSize();
How to set the size of widget
//ImgIcon is a UImage widget.
if (UCanvasPanelSlot* Slot = Cast<UCanvasPanelSlot>(ImgIcon->Slot))
{
    Slot->SetSize(FVector2D(100.f, 100.f));
}
How to set the size of UserWidget(whole UMG UI)
void UUserWidget::SetDesiredSizeInViewport(FVector2D DesiredSize);
How to get the position of widget
//ImgIcon is a UImage widget.
if (UCanvasPanelSlot* Slot = Cast<UCanvasPanelSlot>(ImgIcon->Slot))
{
    FVector2D Pos = Slot->GetPosition();
}

Using CachedGeometry:

ImgIcon->GetCachedGeometry().GetAbsolutePosition();
How to set the position of widget (Modify widget’s screen position at run-time)
void UWidget::SetRenderTranslation(FVector2D Translation)
How to set the position of UserWidget
void UUserWidget::SetPositionInViewport(FVector2D Position, bool bRemoveDPIScale )
How to scale the widget
void UWidget::SetRenderScale(FVector2D Scale)
How to get the screen size
auto geometry = MyWidget->GetCachedGeometry();
auto localSize = geometry.GetLocalSize();
auto screenPosition = geometry.LocalToAbsolute(FVector2D(0, 0)); //TopLeft
auto  screenSize = geometry.LocalToAbsolute(localSize) - screenPosition; // BotRight-TopLeft = real size
How to rotate a widget
void UWidget::SetRenderAngle(float Angle);  //Angle range: (-180, 180)
Mouse clicked position on widget
FReply UMiniMapUI::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
    //Translates a screen position in pixels into the local space of a widget with the given geometry. 
    FVector2D ScreenPos;
    USlateBlueprintLibrary::ScreenToWidgetLocal(this, InGeometry, InMouseEvent.GetScreenSpacePosition(), ScreenPos);

    //Transforms AbsoluteCoordinate into the local space of this Geometry.
    FVector2D LocalWidgetMousePos = USlateBlueprintLibrary::AbsoluteToLocal(InGeometry, InMouseEvent.GetScreenSpacePosition());
    
    return FReply::Handled();
}
NativeConstruct’s trigger timing
if(UMyUserWidget* Widget = WidgetTree->ConstructWidget<UMyUserWidget>(UMyUserWidget::StaticClass()))
{
    //UMyUserWidget::NativeConstruct() would trigger after be AddChild
    MyCanvasPanel->AddChild(Widget);
}

UMyUserWidget::NativeConstruct() would trigger after be AddChild

How to get content of TextBox (Textblock)
FText txt = TxtboxCmdInput->GetText();

Native UMG Cases

Create CanvasPanel As Root Wdiget at Run-time and Add Button Inside It.
void UMyUserWidget::NativeConstruct()
{
    Super::NativeConstruct();
    
    auto MyCanvas = WidgetTree->ConstructWidget<UCanvasPanel>(UCanvasPanel::StaticClass());
    if(MyCanvas)
    {
        auto MyButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass());
        MyCanvas->AddChild(MyButton);
        
        WidgetTree->RootWidget = MyCanvas;
    }
}

Reference: Create widget in pure C++
https://answers.unrealengine.com/questions/470481/create-widget-in-pure-c.html

Filling HorizontalBoxSlot At Run-time
void UBags::NativeConstruct()
{
    Super::NativeConstruct();

    //Get HorizontalBox in Widget Blueprint.
    UHorizontalBox* HorBox = Cast<UHorizontalBox>(GetWidgetFromName(FName("HorizontalBox_62")));
    if (HorBox)
    {
        //Load Item Blueprint
        if (UClass* MyWidgetClass = LoadClass<UMyItemWidget>(NULL, TEXT("WidgetBlueprint'/Game/UI/ItemBP.ItemBP_C'")))
        {
            for (int i = 0; i < 5; i++)
            {
                FString ChildID = FString::Printf(TEXT("MyWidget_%d"), i);
                UMyItemWidget* Item = WidgetTree->ConstructWidget<UMyItemWidget>(MyWidgetClass, ChildID);
                UPanelSlot* Slot = HorBox->AddChild(Item);
                if (UHorizontalBoxSlot* HorSlot = Cast<UHorizontalBoxSlot>(Slot))
                {
                    //Set Size Mode as Fill
                    FSlateChildSize Size(ESlateSizeRule::Type::Fill);
                    HorSlot->SetSize(Size);

                    //Set Align as Center in Horizontal direction.
                    HorSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Center);
                    
                    //Set Align as Center in Vertical direction.
                    HorSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Center);
                }
            }
        }
    }
}

You must pass different argument WidgetName for each child widget when create multiple child using WidgetTree->ConstructWidget(), otherwise events (e.g. OnClicked) of child widget will not work.

Filling UniformGridPanel At Run-time
void UMyUserWidget::NativeConstruct()
{
    Super::NativeConstruct();

    //Get UniformGridPanel in Widget Blueprint.
    UUniformGridPanel* UniGrid = Cast<UUniformGridPanel>(GetWidgetFromName(FName("UniformGridPanel_01")));
    if (UniGrid)
    {
        UButton* MyButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass());
        if(UUniformGridSlot* Slot = UniGrid->AddChildToUniformGrid(MyButton))
        {
            //Set the horizontal index and vertical index of Grid.
            Slot->SetRow(5);
            Slot->SetColumn(5);
        }
    }
}
Get And Set index of Grid of UniformGridPanel In Batch
TArray<UPanelSlot*> Slots = UniformGridPanel->GetSlots();
int  index = 0;
for (UPanelSlot* Slot : Slots)
{
    UUniformGridSlot * UniSlot = Cast<UUniformGridSlot>(Slot);
    if (UniSlot)
    {
        UniSlot->SetRow(index);
        UniSlot->SetColumn(1);
    }
    index++;
}
How to scale or zoom a widget?

For Mouse Zoom:

  • override onMouseWheel
  • add Wheel Delta to Panning Canvas’ Render Transform Scale
  • clamp min result to something above 0 (widgets flip if scaled below 0) and max to your desired max zoom
  • Set Render Scale of the Panning Canvas with the result of the above

Reference: How to scale/zoom a widget with blueprints?
https://answers.unrealengine.com/questions/815202/how-to-scalezoom-a-widget-with-blueprints.html

How to clip widget display area?

Steps:

  • Add a CanvasPanel as the parent of your target widget
  • set the Clipping of CanvasPanel to Clip to Bounds

then the part outside CanvasPanel of your target widget would be clipped.

How to alter widget self’s anchor to the center of itself.

Put the widget into a UCanvasPanel, then set Alignment of this UCanvasPanel as (0.5f, 0.5f):

CanvasPanelSlot->SetAlignment(FVector2D(0.5f, 0.5f));

Alignment may not work properly in PIE(I think it’s a bug), you’d better test it in package.

If UserWidget A is child of UserWidget B, UserWidget A’s Alignment need to be set in UserWidget B, not UserWidget A!!!

How to fade in / out widget

Event for fade begin:

LerpTime = 0.f;
LerpDuration = 1.5f;

FLinearColor SrcColor = MyTextBlock->ColorAndOpacity.GetSpecifiedColor();
FLinearColor DestColor = SrcColor;
DestColor.A = 0.f;

in Tick()

if (LerpTime < LerpDuration)
{
    LerpTime += DeltaSeconds;

    FLinearColor Color = FMath::Lerp<FLinearColor>(SrcColor, DestColor, LerpTime / LerpDuration);

    MyTextBlock->SetColorAndOpacity(Color);
}
Why UMG’s Event OnKeyDown/OnKeyUp is not fired

Solution:
Set Is Focusable enable, and execute SetKeyboardFocus().

void UMyUserWidget::NativeConstruct()
{
    Super::NativeConstruct();

    bIsFocusable = true;
    SetKeyboardFocus();

}

Reference:
https://answers.unrealengine.com/questions/409215/ui-widget-key-events-onkeydownonkeyup-not-generate.html

How to get Widget by Class in current UserWidget

Get all Widget first.
use:

void UWidgetTree::GetAllWidgets(TArray<UWidget*>& Widgets) const

or:

void ForEachWidget(TFunctionRef<void(UWidget*)> Predicate) const;

Then check Widget type:

if(ChildWidget->IsA(UButton::StaticClass()))
{
}

Example:

void UMyUserWidget::NativeConstruct()
{
    Super::NativeConstruct();
    
    if (WidgetTree)
    {
        TArray<UWidget*> Widgets;
        WidgetTree->GetAllWidgets(Widgets);

        for (UWidget* Widget : Widgets)
        {
            if (Widget && Widget->IsA(UButton::StaticClass()))
            {
                if (UButton* Btn = Cast<UButton>(Widget))
                {
                    FScriptDelegate Del;
                    Del.BindUFunction(this, TEXT("PlayBtnOnClickSound"));
                    Btn->OnClicked.Add(Del);
                }
            }
        }
    }
}
How to make WidgetComponent looks like a billboard?
UWidgetComponent::SetWidgetSpace(EWidgetSpace::Screen);

example:

if (!WidgetComp)
{
    WidgetComp = CreateDefaultSubobject<UWidgetComponent>(TEXT("WidgetComponent"));
    WidgetComp->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
    WidgetComp->SetWidgetClass(MyUIClass);
    WidgetComp->SetVisibility(true);
    WidgetComp->SetWidgetSpace(EWidgetSpace::Screen);
}

UWidgetLayoutLibrary

How to get the scale of viewport
FVector2D UWidgetLayoutLibrary::GetViewportScale(UObject* WorldContextObject);
How to get the viewport size
FVector2D UWidgetLayoutLibrary::GetViewportSize(UObject* WorldContextObject);

void APlayerController::GetViewportSize(int32& SizeX, int32& SizeY) const;
How to get the Geometry of all widgets in Viewport or PlayerScreen
FGeometry UWidgetLayoutLibrary::GetViewportWidgetGeometry(UObject* WorldContextObject);

FGeometry UWidgetLayoutLibrary::GetPlayerScreenWidgetGeometry(APlayerController* PlayerController);
How to get mouse position
//Gets the platform's mouse cursor position.  This is the 'absolute' desktop location of the mouse.
FVector2D UWidgetLayoutLibrary::GetMousePositionOnPlatform();

//Gets the platform's mouse cursor position in the local space of the viewport widget.
FVector2D UWidgetLayoutLibrary::GetMousePositionOnViewport(UObject* WorldContextObject);
How to removes all widgets from the viewport
void UWidgetLayoutLibrary::RemoveAllWidgets(UObject* WorldContextObject);

UMG Blueprint Case

How to center my widgets

Set up the widget as follows:

  1. Parent it to your main widget.
  2. Anchor it to (0.5, 0.5).
  3. Set Alignment to (0.5, 0.5).
  4. Set position to (0, 0).

Reference:
https://answers.unrealengine.com/questions/342663/view.html

How to set the scrollbox child button size?

Using a Size Box to wrap the button, and set the Width Override and Height Override of Size Box.

Reference:
https://forums.unrealengine.com/t/how-to-set-the-scrollbox-child-button-size/151275/2

Issues

TextBox doesn’t reset input data even re-create widget (UMG cache)

Caused by:
Parameter WidgetName isn’t null. e.g.:

MyWidget = CreateWidget<UBaseUserWidget>(MyPlayerController, widgetClass, TEXT("TestWidget"));

Solution:
Pass parameter WidgetName with default value:

MyWidget = CreateWidget<UBaseUserWidget>(MyPlayerController, widgetClass);

你讨厌的昨天,是再也回不去的从前。你喜欢的未来,是某一天会怀念的现在。 ---莫书