【UEC++学习】UMG在UEC++中的基本使用与UI的拖拽事件

1. UI的绑定

在C++中创建并设计UMG是非常不方便的事情,因此往往在蓝图的UMG中设计好UI,再在C++中绑定UI,在C++中完成数据的处理、事件的绑定、委托的调用各种事情,只需在UMG中完成页面的设计部分。
我们以下图例子为例

在这里插入图片描述

上图中橙色和红色的框是我们需要绑定的控件,橙色的是本身就存在的基础控件,红色的是我们自定义的一些控件。
对应上图的控件,我们使用UEC++完成绑定如下:

protected:
	/** 自定义类型绑定,对应上图红色标记 */
	UPROPERTY(meta=(BindWidget))
	class UUI_BackpackListBase* OutBackpackList;

	/** 自定义类型绑定 */
	UPROPERTY(meta=(BindWidget))
	class UUI_BackpackListBase* InBackpackList;

	/** 基础控件绑定,对应上图橙色标记 */
	UPROPERTY(meta=(BindWidget))
	class UComboBoxString* ItemTypeComboBox;

注意:在C++中绑定的变量名要与UMG中的名称完全一致,然后UMG继承该类完成绑定,否则继承时会报错。

2. 控件Event的调用

在这里插入图片描述

我们现在需要在C++中调用上图的事件,比如一个Button现在需要调用On Click怎么办呢?我们在C++中使用委托实现。
我们可以在C++源码,或者蓝图看这个委托是什么。

在这里插入图片描述

知道了该调用事件的参数之后就好办了,我们直接创建绑定委托的函数就好

/** 构造函数 */
void UUI_BackpackMain::NativeConstruct()
{
    
    
	Super::NativeConstruct();
	/** 绑定ComboBox的On Selection Changed事件 */
	ItemTypeComboBox->OnSelectionChanged.AddDynamic(this, &UUI_BackpackMain::ComboBoxStringChanged);
;

/** 绑定的代理事件,注意参数要与上图一致 */
void UUI_BackpackMain::ComboBoxStringChanged(FString SelectedOption, ESelectInfo::Type SelectInfo)
{
    
    
	// 执行需要调用的事件
}

3. 基本事件的使用

在UMG中,我们能使用很多重载的函数,包括Construct、Pre Construct等常用的函数。

在这里插入图片描述

在C++中我们输入NativeXXX(),可以找到这些我们熟悉的函数。

在这里插入图片描述

4. UI的拖拽

我们能在基本事件中,找到拖拽相关的函数

/** 当拖拽进入事件 */
virtual void NativeOnDragEnter(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

/** 当拖拽离开事件 */
virtual void NativeOnDragLeave(const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

/** 当拖拽结束时事件 */
virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

/** 继承自父类,当拖拽被发现时 */
virtual void NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) override;

实现流程如下:
(1)在鼠标点击时,使用UWidgetBlueprintLibrary::DetectDragIfPressed,将会调用NativeOnDragDetected
(2)在NativeOnDragDetected中创建拖拽事件,将需要的TagPayload进行传参。
(3)在NativeOnDrop中拿到InOperationTagPayload进行后续的处理。

基本实现如下:

/** 1. 鼠标点击 */
FReply UUI_InventoryCellBase::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
    
    
	Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
	// 如果鼠标左键按下,则返回DetectDrag,调用NativeOnDragDetected()函数
	return UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::LeftMouseButton).NativeReply;
}
/** 2. 创建拖拽事件 */
void UUI_InventoryCellBase::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)
{
    
    
	Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);
	
	/** 创建拖拽事件 */
	UDragDropOperation* Temp = UWidgetBlueprintLibrary::CreateDragDropOperation(BaseDragDropOperation);
	Temp->Tag = DragTag;
	// 拖拽事件的通信参数,Object类型
	Temp->Payload = this;
	// 拖拽时,显示的样式
	Temp->DefaultDragVisual = this;
	// 拖拽事件的相对锚点
	Temp->Pivot = EDragPivot::MouseDown;
	Temp->Offset = FVector2d(0.f,0.f);

	/** 将拖拽事件返回 */
	OutOperation = Temp;
}
/** 3. 在NativeOnDrop中处理拖拽结束后的事情 */
bool UUI_BackpackListBase::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent,
	UDragDropOperation* InOperation)
{
    
    
	/** 使用InOperation进行后续操作 */
	InOperation
	
	return Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);
}

5. 委托的绑定与调用

在UMG中常常使用事件分发器来达到通信的目的,在C++中使用委托实现。

/** 声明委托类 */
DECLARE_DELEGATE(FFlashBackpackListDelegate);
UCLASS()
class LEARNINGPROJECTV5_API UUI_BackpackListBase : public UUI_Base
{
    
    
	// 声明成员变量
	FFlashBackpackListDelegate FlashBackpackListDelegate;
}
/** 绑定委托类 */
DECLARE_DELEGATE(FFlashBackpackListDelegate);
UCLASS()
class LEARNINGPROJECTV5_API UUI_BackpackListBase : public UUI_Base
{
    
    
	// 包含声明委托类
	UPROPERTY(meta=(BindWidget))
	class UUI_BackpackListBase* OutBackpackList;
}

void UUI_BackpackMain::NativeConstruct()
{
    
    
	Super::NativeConstruct();
	// 在需要绑定的时候进行绑定
	OutBackpackList->FlashBackpackListDelegate.BindUObject(this, &UUI_BackpackMain::FlashBackpackList);
}
/** 回到声明委托类执行即可 */
if(FlashBackpackListDelegate.IsBound())
{
    
    
	FlashBackpackListDelegate.Execute();
}

以上,实现了UMG中的事件分发器的效果。

6. 动态创建Widget

// 从指定路径下动态创建Widget,注意路径一定要带.XXXX_C
FString WidgetClassLoadPath = FString(TEXT("/Game/UI/InventoryUI/WBP_InventoryCellBase.WBP_InventoryCellBase_C"));
UClass* ChildWidget = LoadClass<UUserWidget>(NULL, *WidgetClassLoadPath);
if(ChildWidget)
{
    
    
	UUI_InventoryCellBase* SaveChildWidget = CreateWidget<UUI_InventoryCellBase>(GetWorld(), ChildWidget);
	// 设置创建Widget的ItemInfo进行设置
	SaveChildWidget->SetItemInfo(BackpackItemInfos[i], ListDragTag);
	// 将创建的Widget添加到UniformList中
	UniformBackpackList->AddChildToUniformGrid(SaveChildWidget, i,0);
}

猜你喜欢

转载自blog.csdn.net/qq_45617648/article/details/131585950