The answer to this is Bind Widget meta property.
Basic BindWidget Example
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
class UTextBlock* TitleLabel;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
class UImage* IconImage;
- While it’s not mentioned on the UPROPERTY() documentation, it’s one of the most useful tags for you as a UI developer.
- As an aside, check out my full UPROPERTY documentation that includes all properties for BindWidget and others.
- By marking a pointer to a widget as BindWidget, you can create an identically-named widget in a Blueprint subclass of your C++ class, and at run-time access it from the C++.
Here’s a step-by-step process to getting a test working:
- Create a C++ subclass of UUserWidget.
- In it add a member variable that is UWidget* or a subclass of it (e.g. UImage, UTextBlock etc.)
- Mark it with UPROPERTY(meta=(BindWidget)).
- Run the editor and create a Blueprint subclass of your C++ class.
- Create a widget with the same type and exact name as your member variable.
- You can now access the widget from C++.
If any of these steps don’t make sense, check out my introductory series on making UIs with Unreal.
BindExample.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "BindExample.generated.h"
UCLASS(Abstract)
class UBindExample : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
class UTextBlock* ItemTitle;
};
Pros & Cons of using BindWidget and C++
Why would we want to use BindWidget and C++ instead of just writing all our logic in Blueprints?
- Easier to maintain complex logic in C++. No spaghetti-fighting in Blueprints.
- Easier for collaboration, no worries about locking Blueprint assets.
- Requires re-compile to see changes. This time cost can be avoided to some extent by using **Live Coding**.
- Harder for non-programmers to see how data is being populated as the logic is moved from Blueprints to C++.
Optional Widgets
There are some situations where you may have a base C++ class and many different Blueprint subclasses of it. For example a base button class could have common logic in C++, but you could create many different Blueprint subclasses, one for each visual style. Some visual styles might have icons, others might have text, so it would make sense to make the text and icon image widgets optional.
To make a widget optional use meta=(BindWidgetOptional). With this there will be no error shown if the Blueprint class does not have a widget with that name.
