Slate的应用
- 在插件目录下分别在public文件夹和private文件夹下创建HelloSlate.h、CustomBox.h和HelloSlate.cpp、CustomBox.cpp文件。然后再Generate一下。
- 分别在.h和.cpp文件里添加如下代码
HelloSlate.h
#pragma once
#include "SCompoundWidget.h"
#include "DeclarativeSyntaxSupport.h"
#include "CustomBox.h"
class SHelloSlate :public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SHelloSlate)
{}
SLATE_END_ARGS()
//构造
void Construct(const FArguments& InArgs);
//鼠标点击
FReply OnButtonClicked();
//输入结束
void OnTextBoxCommitted(const FText& InputText, ETextCommit::Type CommitType);
public:
//单选框点击
void OnValueChanged(int32 Num);
FString InputText;
int32 Index;
protected:
//单选框数组
TArray< TSharedPtr<SCustomBox> > CustomBoxArray;
};
我们可以使用SLATE_BEGIN_ARGS和SLATE_END_ARGS来声明和构建一个Widget。
官方实例e.g.
SLATE_BEGIN_ARGS( SMyWidget )
, _PreferredWidth( 150.0f )
, _ForegroundColor( FLinearColor::White )
{}
SLATE_ATTRIBUTE(float, PreferredWidth)
SLATE_ATTRIBUTE(FSlateColor, ForegroundColor)
SLATE_END_ARGS()
HelloSlate.cpp
#include "HelloSlate.h"
#include "SOverlay.h"
#include "SBoxPanel.h"
#include "STextBlock.h"
#include "SEditableTextBox.h"
#include "SButton.h"
#include "MessageDialog.h"
#define LOCTEXT_NAMESPACE "HelloSlate"
void SHelloSlate::Construct(const FArguments & InArgs)
{
CustomBoxArray.SetNum(2);//设置单选框数量
ChildSlot
[
SNew(SOverlay)
+ SOverlay::Slot()
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock).Text(LOCTEXT("mingzi","Name:"))
]
+SHorizontalBox::Slot()
.FillWidth(1.0f)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SEditableTextBox)
.OnTextCommitted(this,&SHelloSlate::OnTextBoxCommitted)
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
SNew(STextBlock).Text(LOCTEXT("xingbie", "Gender:"))
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
//以下是自定义控件(将单选框和其对应文本绑定)
SAssignNew(CustomBoxArray[0],SCustomBox)
.Gender("Female")
.IndexNum(0)
.CurrentState(ECheckBoxState::Checked)
.OnChecked(this, &SHelloSlate::OnValueChanged)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
SAssignNew(CustomBoxArray[1], SCustomBox)
.Gender("Male")
.IndexNum(1)
.CurrentState(ECheckBoxState::Unchecked)
.OnChecked(this,&SHelloSlate::OnValueChanged)
]
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
.HAlign(HAlign_Right)
.VAlign(VAlign_Bottom)
[
SNew(SButton).OnClicked(this, &SHelloSlate::OnButtonClicked)
]
]
];
}
以上为Widget的布局,大致如下(一般咱们都会先在UE4里把Widget搞出来,然后再根据Widget再来写slate):
举个小栗子:
~俗话说,有缘千里来相会(懒癌突然附体,别嫌图太长)
FReply SHelloSlate::OnButtonClicked()
{
bool HaveChoose = false;
int32 Index;
if (InputText != "")
{
for (int32 i = 0; i < CustomBoxArray.Num(); i++)
{
if (CustomBoxArray[i]->CurrentState == ECheckBoxState::Checked)
{
HaveChoose = true;
Index = i;
}
}
if (HaveChoose)
{
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("name : " + InputText + "\n" + "Gender : " + CustomBoxArray[Index]->Gender));
}
else
{
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Gender is not null"));
}
}
else
{
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Name is not null "));
}
return FReply::Handled();
}
void SHelloSlate::OnTextBoxCommitted(const FText & InputTex, ETextCommit::Type CommitType)
{
if (CommitType == ETextCommit::OnUserMovedFocus|| ETextCommit::OnEnter)
{
InputText = InputTex.ToString();
}
}
void SHelloSlate::OnValueChanged(int32 Num)
{
//实现单选操作
if (CustomBoxArray[Num]->CurrentState == ECheckBoxState::Unchecked)
{
for (int32 i = 0; i < CustomBoxArray.Num(); i++)
{
if (i != Num)
{
CustomBoxArray[i]->CheckBox->SetIsChecked(ECheckBoxState::Unchecked);
CustomBoxArray[i]->CurrentState = ECheckBoxState::Unchecked;
}
}
}
}
#undef LOCTEXT_NAMESPACE
CustomBox.h
#pragma once
#include "CoreMinimal.h"
#include "SCompoundWidget.h"
#include "SCheckBox.h"
//声明委托
DECLARE_DELEGATE_OneParam(FOnChecked,int32)
class SCustomBox :public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCustomBox)
{
_Gender = "";
}
//传递代理
SLATE_EVENT(FOnChecked, OnChecked)
//传递参数
SLATE_ARGUMENT(ECheckBoxState, CurrentState)
SLATE_ARGUMENT(FString, Gender)
SLATE_ARGUMENT(int32, IndexNum)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
FOnChecked OnChecked;
FString Gender;
ECheckBoxState CurrentState;
void ChangeBoxState(ECheckBoxState State);
TSharedPtr<SCheckBox> CheckBox;
int32 IndexNum;
};
CustomBox.cpp
#include "CustomBox.h"
#include "STextBlock.h"
void SCustomBox::Construct(const FArguments & InArgs)
{
OnChecked = InArgs._OnChecked;
Gender = InArgs._Gender;
CurrentState = InArgs._CurrentState;
IndexNum = InArgs._IndexNum;
ChildSlot
[
SAssignNew(CheckBox,SCheckBox)
.IsChecked(CurrentState)
.OnCheckStateChanged(this,&SCustomBox::ChangeBoxState)
[
SNew(STextBlock)
.Text(FText::FromString(Gender))
]
];
}
void SCustomBox::ChangeBoxState(ECheckBoxState NewState)
{
//执行代理
OnChecked.ExecuteIfBound(IndexNum);
CurrentState = NewState;
}
最后效果如下所示: