简述
在UE4开发中,我们想使用UMG创建显示界面,而在C++代码中编写逻辑处理代码。这样就需要UMG和C++进行交互,即在C++中引用UMG中的控件,并进行事件绑定等操作
交互方法
一,强转子集
GetRootWidget() //获取根节点
GetChildAt() //获取子节点
UMG控件呈树状结构,根据根节点可以获取到所有的子节点
二,反射绑定
UPROPERTY(Meta = (BindWidget))
UButton *ButtonOne;
绑定的类型和名称必须和蓝图内的一致
三,根据控件名获取
GetWidgetFromName()
获取到UWidget*类型,强转成指定类型
实例应用
创建C++空项目,新建两个C++类,分别继承于HUD和UserWidget,命名为MyHUD和MyWidget
创建两个继承于MyHUD和MyWidget的蓝图类,即BP_MyHUD和BP_MyWidget
BP_MyWidget需先创建UMG蓝图,然后在UMG蓝图中指定继承的父类
源码
MyHUD.h
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "MyHUD.generated.h"
UCLASS()
class PROJECTDEMO2_API AMyHUD : public AHUD
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override;
public:
UPROPERTY(EditAnywhere, Category = "UserWidget")
TSubclassOf WidgetClass;
};
MyHUD.cpp
#include "MyHUD.h"
#include "Kismet/GameplayStatics.h"
#include "MyWidget.h"
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
UMyWidget* widget = CreateWidget(GetWorld(), WidgetClass);
if (widget != nullptr)
{
widget->AddToViewport();
}
//获取控制器
APlayerController *myPlayerController = Cast(UGameplayStatics::GetPlayerController(GetWorld(), 0));
//设置鼠标输入模式
if (myPlayerController != nullptr)
{
myPlayerController->bShowMouseCursor = true;
FInputModeGameOnly InputMode;
InputMode.SetConsumeCaptureMouseDown(true);
myPlayerController->SetInputMode(InputMode);
}
}
MyWidget.h
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "MyWidget.generated.h"
class UImage;
class UCanvasPanel;
class UButton;
UCLASS()
class PROJECTDEMO2_API UMyWidget : public UUserWidget
{
GENERATED_BODY()
public:
UMyWidget(const FObjectInitializer& objectInitializer);
virtual bool Initialize() override;
UFUNCTION()
void ButtonOneEvent();
UFUNCTION()
void ButtonTwoEvent();
UFUNCTION(BlueprintCallable, Category = "UserWidget")
void ButtonThreeEvent();
public:
//反射绑定
UPROPERTY(Meta = (BindWidget))
UButton *ButtonOne;
UCanvasPanel* rootPanel;
};
MyWidget.cpp
#include "MyWidget.h"
#include "CanvasPanel.h"
#include "Image.h"
#include "Button.h"
#include "TextBlock.h"
#include "Text.h"
UMyWidget::UMyWidget(const FObjectInitializer& objectInitializer) :Super(objectInitializer)
{
}
bool UMyWidget::Initialize()
{
if (!Super::Initialize())
{
return false;
}
//ButtonOne
ButtonOne->OnClicked.__Internal_AddDynamic(this, &UMyWidget::ButtonOneEvent, FName("ButtonOneEvent"));
//ButtonTwo
rootPanel = Cast(GetRootWidget());
if (rootPanel)
{
UButton* ButtonTwo = Cast(rootPanel->GetChildAt(2));
ButtonTwo->OnClicked.__Internal_AddDynamic(this, &UMyWidget::ButtonTwoEvent, FName("ButtonTwoEvent"));
}
//ButtonThere
UButton* ButtonThere = (UButton*)GetWidgetFromName(TEXT("ButtonThree"));
FScriptDelegate ButTwoDel;
ButTwoDel.BindUFunction(this, "ButtonThreeEvent");
ButtonThere->OnReleased.Add(ButTwoDel);
return true;
}
void UMyWidget::ButtonOneEvent()
{
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "ButtonOneEvent");
}
}
void UMyWidget::ButtonTwoEvent()
{
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "ButtonTwoEvent");
}
}
void UMyWidget::ButtonThreeEvent()
{
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 20, FColor::Yellow, "ButtonThreeEvent");
}
}
注:在MyWidget中我们获取了Button的引用,并绑定OnClicked事件,在MyHUD中设置了鼠标显示模式和添加了Widget到视口。
编译保存,在World Settings指定HUD Class为BP_MyHUD