How can I handle Blueprint-Widgets in C++

Hi,

I am not sure, if this is possible, but I want to use a Widget, created within the Blueprint-Editor, within C++. I just designed the whole widget in blueprints (just drag and drop buttons and stuff), but I want to handle click-events etc. in C++. Is there a way to do so?

Let me know, if this is a stupid question. I am a very beginner and most of the time I don’t really know what I am doing :wink:

Thanks
sl

I think your best option would be to create the widget elements you need in C++ (i can help you with that if you need) and then “manipulate” them in your widget blueprint.
That’s the only way your widget elements will be available in C++, because you can access C++ elements in Blueprint, but not the other way around.

Okay, great and thank you for your response. Basically, I am using an Image (just a picture of a keypad) and invisible buttons, which I place on this image. Which means, I would need to create those buttons in c++. Can I replace them in blueprints afterwards (and add mouse-over-effects etc)?

You can declare a button for instance with the BindWidget macro like this:

UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
    UButton* MyButton;

If you create a Button in UMG and name it the same as in this property (MyButton) you will essentially create the button referenced in C++, and you can reference it that way.

You can also use this in order to make that binding optional, given that the previous way makes it mandatory that you create that widget in UMG:

UPROPERTY(BlueprintReadWrite, meta = (BindWidget, OptionalWidget=true)

Hi, thank you again.

What I tried now: I made a widget c++ class and in the umg class settings I set this as a parent class. Is this the correct way? It is still not working, the constructor is not called. This is what my code looks like, so far:

The .h-file

UCLASS()
class TESTGAME_API UKeypadUserWidget : public UUserWidget
{
GENERATED_BODY()

public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “My New User Widget”)
FString MyNewWidgetName;

UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
	UButton* key0;

// other keys ...

UKeypadUserWidget(FVTableHelper &Helper);

void OnButtonClicked();

};

… and the cpp file

UKeypadUserWidget::UKeypadUserWidget(FVTableHelper &Helper):Super(Helper)
{
UPanelWidget* RootWidget = Cast(GetRootWidget());

key0 = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass());
key0->OnClicked.AddDynamic(this, &UKeypadUserWidget::OnButtonClicked);
RootWidget->AddChild(key0);

// other keys ...

}

void UKeypadUserWidget::OnButtonClicked()
{
UE_LOG(LogTemp, Warning, TEXT(“Button clicked”));
return;
}

Sorry, I could not find an option to post code properly.

You don’t need to do that in the constructor. The one thing you would need to do is assigning the OnClicked event, but you have to actually create the button in the WidgetBlueprint, and call it “key0” in order to assign it to your C++ variable.

Also if the OnClicked binding doesn’t work in the class’s constructor, try overriding the widget’s OnNativeConstruct event and bunding the OnClicked there!

i think u can create a c++ class based on a widget cant u?

I used the wrong constructor. But I put it in NativeConstruct() now. The widget is loading, but I still cannot raise the OnButtonClicked by clicking the buttons. They are all named the same way, as they are in the widget (key0, key1, …).

Hopefully, this is the last question, but do you have any idea, what could be wrong/missing? All I do in the NativeConstruct()-Function, is to call Super::NativeConstruct() and then add the OnClick for each button in this way: key0->OnClicked.AddDynamic(this, &UKeypadUserWidget::OnButtonClicked);

This is the code from the PlayerController, maybe I’ve been missing something there?

if (wMainMenu) // Check if the Asset is assigned in the blueprint.
{
// Create the widget and store it.
MyMainMenu = CreateWidget(this, wMainMenu);

	// now you can use the widget directly since you have a referance for it.
	// Extra check to  make sure the pointer holds the widget.
	if (MyMainMenu)
	{
		//let add it to the view port
		MyMainMenu->AddToViewport();
	}

	FInputModeUIOnly Mode;
	Mode.SetWidgetToFocus(MyMainMenu->GetCachedWidget());
	SetInputMode(Mode);

	//Show the Cursor.
	bShowMouseCursor = true;
}

Okay, my bad, I set a breakpoint and didn’t have a look into the log-files for a while. It is working, it is just the debugger, which isn’t stopping at the break point. Thank you very much for your help!

Great :smiley: I’m glad you got it working!