# C++显示UI
# 基本场景
# UI的鼠标事件
下面是鼠标在UI上进入离开,点击事件的判定:
//================================头文件===================================
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "MyTestUserWidget.generated.h"
/**
*
*/
UCLASS()
class TESTLEARN20211220_API UMyTestUserWidget : public UUserWidget
{
GENERATED_BODY()
public:
virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;
virtual FReply NativeOnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) override;
virtual FReply NativeOnMouseButtonUp( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) override;
};
//================================cpp文件===================================
#include "MyTestUserWidget.h"
void UMyTestUserWidget::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
UE_LOG(LogTemp,Warning,TEXT("on mouse enter!"));
}
void UMyTestUserWidget::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
{
UE_LOG(LogTemp,Warning,TEXT("on mouse leave!"));
}
FReply UMyTestUserWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
UE_LOG(LogTemp,Warning,TEXT("on mouse down!"));
return FReply::Handled();
}
FReply UMyTestUserWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
UE_LOG(LogTemp,Warning,TEXT("on mouse up!"));
return FReply::Handled();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
注意:
- Actor类的蓝图有一个BlockInput,如果把这个勾选,是无法进行操作了。
- 如果要3DUI也要有这些事件,需要勾选Interaction->Receive Hardware Input。
# UI初始化
关于UI的初始化有几个方法:
- virtual void NativeOnInitialized() override;
- 在游戏运行中的非模板实例调用,因为Construct/Destruct适用于底层的Slate,每个UserWidget只调用一次。如果你有只做一次的事,比如绑定BindWidget属性的事件上的回调函数,可以在这里做。
- virtual void NativePreConstruct() override;
- 被游戏和编辑器调用,允许用户运行初始化脚本来让控件在编辑器Designer中有更好的预览,同样在游戏运行时它也会在调用。
- 这个仅用于使用本地的数据来进行表面的更新,你不能安全地获取任何游戏相关的状态,如果你调用了并不打算在编辑器下运行的逻辑,你会直接把editor搞崩溃。
- 在这个事件中如果使用蓝图的代码来保存资产,这会直接导致崩溃,你可以在Editor Preferences中关闭PreConstruct。
- virtual void NativeConstruct() override;
- 在底层slate被创建后调用,这取决于slate对象如何被用的。这个事件会因为UserWidget增加移除到视口上而被调用多次,如果你需要called-once-when-created事件,使用OnInitialized。
- virtual void NativeDestruct() override;
- 当一个UserWidget不再被引用时,这会导致slate资源被销毁,就像Construct事件被调用多次。
- 在创建UserWidget时,调用NativeOnInitialized。
- 在RemoveFromParent时,调用NativeDestruct。
- 在AddToViewport时,调用NativePreConstruct和NativeConstruct。
# 场景应用
用C++显示一个UI,并控制该UI显示文字。
# 操作步骤
创建UIGameInstance.cpp:
//===========================UIGameInstance.h======================= // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Engine/GameInstance.h" #include "MyUserWidget.h" #include "UIGameInstance.generated.h" /** * */ UCLASS() class TEST20210310_API UUIGameInstance : public UGameInstance { GENERATED_BODY() UUIGameInstance(); void DelayFunction(); FTimerHandle myTimerHandle; TSubclassOf<class UMyUserWidget> MenuClassSource; UMyUserWidget* Menu; virtual void Init(); }; //===================UIGameInstance.cpp===================== // Fill out your copyright notice in the Description page of Project Settings. #include "UIGameInstance.h" UUIGameInstance::UUIGameInstance() { ConstructorHelpers::FClassFinder<UMyUserWidget> MenuClassFinder(TEXT("/Game/TestUI")); MenuClassSource = MenuClassFinder.Class; } void UUIGameInstance::DelayFunction() { Menu = CreateWidget<UMyUserWidget>(GetWorld(), MenuClassSource); if (Menu) { Menu->SetupUI(); GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Run Init Progress!")); //Menu->SetVisibility(ESlateVisibility::Visible); /*APlayerController* PlayerController = GetWorld()->GetFirstPlayerController(); FInputModeUIOnly InputModeData; InputModeData.SetWidgetToFocus(Menu->TakeWidget()); InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); PlayerController->SetInputMode(InputModeData); PlayerController->bShowMouseCursor = true;*/ } } void UUIGameInstance::Init() { GetWorld()->GetTimerManager().SetTimer(myTimerHandle, this, &UUIGameInstance::DelayFunction, 3.0f, false); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56C++创建UserWidget:
//=========================MyUserWidget.h========================== #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "Runtime/UMG/Public/Components/TextBlock.h" #include "MyUserWidget.generated.h" /** * */ UCLASS() class TEST20210310_API UMyUserWidget : public UUserWidget { GENERATED_BODY() public: void SetupUI(); UPROPERTY(meta = (BindWidget)) class UTextBlock* ItemTitle; }; //========================MyUserWidget.cpp======================= #include "MyUserWidget.h" void UMyUserWidget::SetupUI() { this->AddToViewport(); ItemTitle->SetText(FText::FromString(TEXT("谢谢"))); //ItemTitle->SetText(NSLOCTEXT("MyOtherNamespace", "HelloWorld","лл")); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34在UE4中创建蓝图继承MyUserWidget,并创建一个名为"ItemTitle"的TextBlock。