[UE4]UMG使用实例(C++)
Keywords:UE4、UMG、C++、Widget、Demo、Example、示例、实例、例子、UI
两年前写过一篇C++操控UMG蓝图的文章,当时写的有点乱,非核心的东西写了不少,干扰阅读。
这里用4.18版本重新做一个C++控制UMG的精简实例,完整工程下载见文章底部。
假设新建的测试工程叫:UMGTest。实现一个简单的功能:点击按钮,动态替换掉按钮上的背景图片。
UMG使用步骤如下:
1,确保Build.cs中引用了UMG和Slate。
例如:
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UMG"
}
);
2,创建自定义的UMG C++类。
在UE4编辑器中点击:File -》 New C++ Class。
弹出的对话框中,勾选Show All Classes,并找到UserWidget,选中后再点击Next。表示选择UserWidget作为我们创建的C++ class的父类。
起好名字(这里命名为:MyUserWidget),点击创建
3,创建UMG蓝图
在内容浏览器中,右键点击:User Interface -》 Widget Blueprint。
修改蓝图名称并保存。这里命名为:NewWidgetBlueprint。
然后双击打开UMG蓝图,拖拽一个Button组件到编辑视图中。假设给这个Button命名为:BtnChangeImg。
并设置按钮的大小,这里设置为和图片素材一样的大小
再拖拽一个Image组件到这个Button内
并设置Image组件的大小
然后切换到Graph视图
然后再点击Class Settings
再找到Parent Class,设置为之前创建的C++类:MyUserWidget。
4,添加图片资源
我这里使用两张PNG图片,导入UE4即可。
5,编写自定义UserWidget的C++代码
添加需要的头文件,比如我们在头文件中使用了UImage,那么需要指明这个UImage所在的头文件。例如:
#include "Components/Image.h"
具体代码如下:
UMGTestGameModeBase.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "UMGTestGameModeBase.generated.h"
/**
*
*/
UCLASS()
class UMGTEST_API AUMGTestGameModeBase : public AGameModeBase
{
GENERATED_BODY()
public:
AUMGTestGameModeBase();
protected:
virtual void BeginPlay() override;
private:
//UMG蓝图的实例对象,用于显示在游戏的Viewport
UUserWidget* MyWidgetInstance;
};
UMGTestGameModeBase.cpp
#include "UMGTestGameModeBase.h"
#include "Blueprint/UserWidget.h"
AUMGTestGameModeBase::AUMGTestGameModeBase()
{
MyWidgetInstance = nullptr;
}
void AUMGTestGameModeBase::BeginPlay()
{
//检测Widget对象是否存在,如果存在则移除掉。
if (MyWidgetInstance)
{
MyWidgetInstance->RemoveFromViewport();
MyWidgetInstance = nullptr;
}
//加载自定义UMG的class,通过这个class创建Widget对象,并显示在界面中。
if (UClass* MyWidgetClass = LoadClass<UUserWidget>(nullptr, TEXT("WidgetBlueprint'/Game/NewWidgetBlueprint.NewWidgetBlueprint_C'")))
{
if (APlayerController* PC = GetWorld()->GetFirstPlayerController())
{
MyWidgetInstance = CreateWidget<UUserWidget>(PC, MyWidgetClass);
if (MyWidgetInstance)
{
MyWidgetInstance->AddToViewport();
}
}
}
}
MyUserWidget.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "MyUserWidget.generated.h"
/**
*
*/
UCLASS()
class UMGTEST_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
public:
UMyUserWidget(const FObjectInitializer& ObjectInitializer);
protected:
virtual void NativeConstruct() override;
UFUNCTION()
void OnBtnChangeImgClick();
private:
//英雄头像的显示图片
UImage* HeroIcon;
//两张图片素材
UTexture2D* TexHero1;
UTexture2D* TexHero2;
//显示状态标识
int ImgFlag;
};
MyUserWidget.cpp
#include "MyUserWidget.h"
#include "Components/Button.h"
#include "Engine/Texture2D.h"
UMyUserWidget::UMyUserWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
HeroIcon = nullptr;
TexHero1 = nullptr;
TexHero2 = nullptr;
ImgFlag = 0;
}
void UMyUserWidget::NativeConstruct()
{
Super::NativeConstruct();
//根据组件ID查找Image组件
if (UImage* img = Cast<UImage>(GetWidgetFromName(FName(TEXT("ImgHero")))))
{
HeroIcon = img;
}
//根据组件ID查找Button组件,并为其添加Click回调事件
if (UButton* btn = Cast<UButton>(GetWidgetFromName("BtnChangeImg")))
{
FScriptDelegate Del;
Del.BindUFunction(this, "OnBtnChangeImgClick");
btn->OnClicked.Add(Del);
}
//加载图片资源
if (TexHero1)
{
//如果已经加载过,则先销毁掉
TexHero1->ConditionalBeginDestroy();
TexHero1 = nullptr;
GEngine->ForceGarbageCollection(true);
}
TexHero1 = LoadObject<UTexture2D>(nullptr, TEXT("Texture2D'/Game/pic_01.pic_01'"));
if (TexHero2)
{
TexHero2->ConditionalBeginDestroy();
TexHero2 = nullptr;
GEngine->ForceGarbageCollection(true);
}
TexHero2 = LoadObject<UTexture2D>(nullptr, TEXT("Texture2D'/Game/pic_02.pic_02'"));
}
void UMyUserWidget::OnBtnChangeImgClick()
{
//切换显示图片
if (HeroIcon && TexHero1 && TexHero2)
{
HeroIcon->SetBrushFromTexture(ImgFlag ? TexHero1 : TexHero2);
ImgFlag = ImgFlag == 0 ? 1 : 0;
}
}
最终效果
按Shift+F1切换到光标显示模式,然后点击按钮,就可以切换图片。
完整工程下载地址:
http://pan.baidu.com/s/1i5em6TR
不应有恨,何事长向别时圆?—苏轼《水调歌头》