GetRootWidget() is always nullptr on custom UUserWidget spawned with CreateWidget.

I’m trying to create and spawn a widget programmatically and I’m having trouble understanding how it should be done. I’ve created a class deriving from UUserWidget and I think I’ve got it working as it should except for being able to add my canvas panel holding all child widgets to the UUserWidget itself. The problem I’m having is that GetRootWidget() always returns nullptr despite the fact that the creation of the widget seemingly succeeded. Here’s what the class looks like:

ChatboxUI.h



UCLASS()
class PROJECTAZURE_API UChatboxUI : public UUserWidget
{
	GENERATED_BODY()
	
public:
	UChatboxUI(const FObjectInitializer& ObjectInitializer);

	static FSlateFontInfo *FInfo;
	void Init();

protected:
	virtual void NativeConstruct() override;

private:

	UFont *Typeface;
	UCanvasPanel *MainPanel;
	UOverlay *ChatboxUI;
	UImage *ChatboxBackground;
	UVerticalBox *ChatboxElements;
	UScrollBox *ChatScrollBox;
	UEditableTextBox *ChatboxInput;
	UTexture2D *BGTexture;

};


ChatboxUI.cpp



FSlateFontInfo *UChatboxUI::FInfo = nullptr;

UChatboxUI::UChatboxUI(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{

	static ConstructorHelpers::FObjectFinder<UFont> Meiryo(TEXT("Font'/Game/Fonts/Meiryo.Meiryo'"));
	if(Meiryo.Succeeded() == false)
		DebugMessage("Failed to load Meiryo font");
	else
	{
		Typeface = Meiryo.Object;
	}
	static ConstructorHelpers::FObjectFinder<UTexture2D> BGTex(TEXT("Texture2D'/Game/UI/Chatbox/chatboxbg.chatboxbg'"));
	if(BGTex.Succeeded() == false)
		DebugMessage("Failed to load Chatbox background texture");
	else
	{
		BGTexture = BGTex.Object;
	}

	if(FInfo == nullptr)
	{
		FInfo = new FSlateFontInfo();
		FInfo->FontObject = Typeface;
		FInfo->Size = 14;
	}
	MainPanel = NewObject<UCanvasPanel>();
	ChatboxUI = NewObject<UOverlay>();
	ChatboxBackground = NewObject<UImage>();
	ChatboxElements = NewObject<UVerticalBox>();
	ChatScrollBox = NewObject<UScrollBox>();
	ChatboxInput = NewObject<UEditableTextBox>();

}

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

}

void UChatboxUI::Init()
{
	FSlateBrush BGBrush;
	FSlateBrush DrawAsNone;
	FScrollBoxStyle ScrollBoxStyle;
	FSlateChildSize ScrollBoxSize;
	BGBrush.SetResourceObject(BGTexture);
	BGBrush.Tiling = ESlateBrushTileType::Both;
	BGBrush.TintColor = FSlateColor(FLinearColor(1.0f, 1.0f, 1.0f, 0.5f));
	DrawAsNone.DrawAs = ESlateBrushDrawType::NoDrawType;
	ScrollBoxStyle.BottomShadowBrush = DrawAsNone;
	ScrollBoxStyle.TopShadowBrush = DrawAsNone;
	ScrollBoxStyle.LeftShadowBrush = DrawAsNone;
	ScrollBoxStyle.RightShadowBrush = DrawAsNone;
	ScrollBoxSize.SizeRule = ESlateSizeRule::Fill;
	ScrollBoxSize.Value = 1.0f;
	ChatboxBackground->SetBrush(BGBrush);
	ChatboxUI->AddChild(ChatboxBackground);
	ChatboxUI->AddChild(ChatboxElements);
	UOverlaySlot *OverlaySlot1 = Cast<UOverlaySlot>(ChatboxUI->GetSlots()[0]);
	OverlaySlot1->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
	OverlaySlot1->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
	UOverlaySlot *OverlaySlot2 = Cast<UOverlaySlot>(ChatboxUI->GetSlots()[1]);
	OverlaySlot2->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
	OverlaySlot2->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
	ChatScrollBox->WidgetStyle = ScrollBoxStyle;
	ChatboxElements->AddChild(ChatScrollBox);
	ChatboxElements->AddChild(ChatboxInput);
	UVerticalBoxSlot *VerticalBoxSlot = Cast<UVerticalBoxSlot>(ChatboxElements->GetSlots()[0]);
	VerticalBoxSlot->Size = ScrollBoxSize;
	MainPanel->AddChildToCanvas(ChatboxUI);
	UCanvasPanelSlot *UISlot = Cast<UCanvasPanelSlot>(MainPanel->GetSlots()[0]);
	UISlot->SetSize(FVector2D(780.f, 344.f));
	UPanelWidget* RootWidget = Cast<UPanelWidget>(GetRootWidget());
	if(RootWidget != nullptr)
		RootWidget->AddChild(MainPanel);
	else
		DebugMessage("RootWidget == nullptr");
	if(GetRootWidget() == nullptr)
		DebugMessage("GetRootWidget() == nullptr");
}


Both UPanelWidget *RootWidget and GetRoodWidget() are always nullptr so I can’t add my main canvas panel to the UUserWidget.

This is how I create the widget and initialize it:



	Chatbox = CreateWidget<UChatboxUI>(LocalController, UChatboxUI::StaticClass());
	Chatbox->Init();


I’ve tried using a world pointer in CreateWidget too but to no avail. I’m seriously stumped. Any ideas or help would be much appreciated :slight_smile:

1 Like

I thoroughly believe that c++ built widgets aren’t even supported anymore. If you look through all of the forums on it there aren’t any successful answers. I’ve been trying to solve this for days now and I think they simply just don’t care to add support for it.