网站模板可视化编辑,沃尔玛超市,游戏推广代理加盟,手机购物软件有哪些创建StreeView的多列样式怎么就像是创建单行单列差不多#xff1f;貌似就是在单行单列中加入了多列widget?
示例代码
DetailTabWidget
#pragma once
#include TreeViewItemBase.hclass SDetailTabWidget : public SCompoundWidget
{SLATE_BEGIN_ARGS(SDetailT…
创建StreeView的多列样式怎么就像是创建单行单列差不多貌似就是在单行单列中加入了多列widget?
示例代码
DetailTabWidget
#pragma once
#include TreeViewItemBase.hclass SDetailTabWidget : public SCompoundWidget
{SLATE_BEGIN_ARGS(SDetailTabWidget){}SLATE_END_ARGS()void Construct(const FArguments InArgs);private:TSharedPtrSWidgetSwitcher WidgetSwitcher;TSharedPtrSTreeViewTSharedRefFTreeViewItemBase TreeViewItem;TArrayTSharedRefFTreeViewItemBase TreeViewSource;public:TSharedRefclass ITableRow GenerateTreeViewRow(TSharedRefFTreeViewItemBase ItemBase, const TSharedRef class STableViewBase TableViewBase);void OnGetChildren(TSharedRefFTreeViewItemBase ItemBase, TArrayTSharedRefFTreeViewItemBase OutChildren);void SetItemData();
};#include DetailTabWidget.h#include TreeViewItemBaseBool.h
#include Widgets/Layout/SWidgetSwitcher.hvoid SDetailTabWidget::Construct(const FArguments InArgs)
{ChildSlot[SAssignNew(WidgetSwitcher, SWidgetSwitcher)SWidgetSwitcher::Slot().HAlign(HAlign_Center).VAlign(VAlign_Center)[SNew(STextBlock).Text(FText::FromString(This DetailTab Panel))]SWidgetSwitcher::Slot().HAlign(HAlign_Fill).VAlign(VAlign_Fill)[SAssignNew(TreeViewItem,STreeViewTSharedRefFTreeViewItemBase).TreeItemsSource(TreeViewSource)//委托生成每一行绑定自定义方法事件触发时生成.OnGenerateRow(this, SDetailTabWidget::GenerateTreeViewRow).OnGetChildren(this,SDetailTabWidget::OnGetChildren).HeaderRow(SNew(SHeaderRow)SHeaderRow::Column(Name).HeaderContentPadding(FMargin(0)).FillWidth(0.4f)[SNew(SBorder).Padding(FMargin(10,5,5,5))[SNew(STextBlock).Text(FText::FromString(TEXT(名 称)))]]SHeaderRow::Column(Value).HeaderContentPadding(FMargin(0)).FillWidth(0.4f)[SNew(SBorder).Padding(FMargin(10,5,5,5))[SNew(STextBlock).Text(FText::FromString(TEXT(属 性)))]])]];SetItemData();
}TSharedRefclass ITableRow SDetailTabWidget::GenerateTreeViewRow(TSharedRefFTreeViewItemBase ItemBase,const TSharedRefclass STableViewBase TableViewBase)
{return SNew(SMultiTableRow, TableViewBase,ItemBase);
}void SDetailTabWidget::OnGetChildren(TSharedRefFTreeViewItemBase ItemBase,TArrayTSharedRefFTreeViewItemBase OutChildren)
{ItemBase-Getchildren(OutChildren);
}void SDetailTabWidget::SetItemData()
{TSharedRefFTreeViewItemBaseBool BoolItem MakeShareable(new FTreeViewItemBaseBool());TreeViewSource.Add(BoolItem);TreeViewItem-RequestTreeRefresh();WidgetSwitcher-SetActiveWidgetIndex(1);} TreeViewItemBase
#pragma once// Item
class FTreeViewItemBase : public TSharedFromThisFTreeViewItemBase
{
public:virtual TSharedRefSWidget MakeNameWidget() 0;virtual TSharedRefSWidget MakeValueWidget() 0;void Getchildren(TArrayTSharedRefFTreeViewItemBase OutChildren) const{OutChildren Children;}
private:TArrayTSharedRefFTreeViewItemBase Children;
};// Row单行多列
class SMultiTableRow : public SMultiColumnTableRowTSharedRefFTreeViewItemBase
{SLATE_BEGIN_ARGS(SMultiTableRow){}SLATE_END_ARGS()virtual TSharedRefSWidget GenerateWidgetForColumn(const FName ColumnName) override;void Construct(const FArguments InArgs, const TSharedRefSTableViewBase InOwnerTableView, const TSharedRefFTreeViewItemBase InTreeViewItemBase);
private:TWeakPtrFTreeViewItemBase TreeViewItemBasePtr;
};
#include TreeViewItemBase.hTSharedRefSWidget SMultiTableRow::GenerateWidgetForColumn(const FName ColumnName)
{if (ColumnName.IsEqual((TEXT(Name)))){return TreeViewItemBasePtr.Pin()-MakeNameWidget();}if (ColumnName.IsEqual(TEXT(Value))){return TreeViewItemBasePtr.Pin()-MakeValueWidget(); }return SNullWidget::NullWidget;
}void SMultiTableRow::Construct(const FArguments InArgs, const TSharedRefSTableViewBase InOwnerTableView,const TSharedRefFTreeViewItemBase InTreeViewItemBase)
{TreeViewItemBasePtr InTreeViewItemBase;STableRow::FArguments ParentArgs;ParentArgs.Padding(FMargin(0,0,0,0));SMultiColumnTableRow::Construct(ParentArgs, InOwnerTableView);
}TreeViewItemBaseBool
#pragma once
#include TreeViewItemBase.hclass FTreeViewItemBaseBool : public FTreeViewItemBase
{
public:virtual TSharedRefSWidget MakeNameWidget() override;virtual TSharedRefSWidget MakeValueWidget() override;private:void OnCheckStateChanged(ECheckBoxState CheckState);ECheckBoxState GetCheckBoxState() const;bool Value;};#include TreeViewItemBaseBool.hTSharedRefSWidget FTreeViewItemBaseBool::MakeNameWidget()
{return SNew(STextBlock).Text(FText::FromString(TEXT(选中测试Bool)));
}TSharedRefSWidget FTreeViewItemBaseBool::MakeValueWidget()
{return SNew(SCheckBox).OnCheckStateChanged(this, FTreeViewItemBaseBool::OnCheckStateChanged).IsChecked(this, FTreeViewItemBaseBool::GetCheckBoxState);}void FTreeViewItemBaseBool::OnCheckStateChanged(ECheckBoxState CheckState)
{Value CheckState ECheckBoxState::Checked ? true : false;
}ECheckBoxState FTreeViewItemBaseBool::GetCheckBoxState() const
{return Value? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}目录结构 必备条件
StreeView的多列创建需要的必备条件:
数据基类
CustomItemBase
#pragma once
/*
----------------------------------
| Name | Value |
----------------------------------
| 香蕉 | 真正的香蕉 |
----------------------------------
*/// 构建一个基类相当于创建一个空的价签其中包括名字价格具体怎么填由子类决定
class FCustomItemBase : public TSharedFromThisFCustomItemBase
{
public:virtual ~FCustomItemBase() {}// 比如要卖香蕉名字香蕉 Value 价格virtual TSharedRefSWidget MakeNameWidget() 0;virtual TSharedRefSWidget MakeValueWidget() 0;//当展示时需要先获取到这个价签后才能知道这是为哪个商品准备的价签即名字价格void GetChildrens(TArrayTSharedRefFCustomItemBase OutChildren) const{ OutChildren Childrens;};private://用于保存传入的参数并通过OutChildren传出去TArrayTSharedRefFCustomItemBase Childrens;
};/*
----------------------------------
| Name | Value |
----------------------------------
FCustomItemBase中有两个属性(name、Value)所以制作价签时就需要预留两个空位使用SMultiColumnTableRow多列样式
创建继承至class SMultiColumnTableRow的类,查看基类样式为SMultiColumnTableRow : public STableRowItemType
解释为 S类名 public 基类价签的引用,有几个属性就安排几个位置即有两个属性就安排两列这是S类,所以需要S类的构造方法
如果是单列STableRow,每行就只能放一个属性,明白了吗
----------
| Name |
----------
*/class SMultiDetailTableRow : public SMultiColumnTableRowTSharedRefFCustomItemBase
{SLATE_BEGIN_ARGS(SMultiDetailTableRow){}SLATE_END_ARGS()// 父类SMultiColumnTableRow中的方法,动态生成不同列的显示内容,必须实现的方法virtual TSharedRefSWidget GenerateWidgetForColumn( const FName InColumnName ) override;// 父类方法中默认两个参数,第三个参数是因为创建时必须有FCustomItemBase才能正确显示void Construct(const FArguments InArgs, const TSharedRefSTableViewBase OwnerTableView,TSharedRefFCustomItemBase InCustomItemBase);
private:// 这个弱指针是为了初始化时将传进来的FCustomItemBase赋值给CustomItemBase用于保存TWeakPtrFCustomItemBase CustomItemBase;
};#include CustomItemBase.h//一行多列
TSharedRefSWidget SMultiDetailTableRow::GenerateWidgetForColumn(const FName InColumnName)
{// 判断InColumnName,如果传入的是名字,就在价签的name中添加名字if (InColumnName.IsEqual(TEXT(Name))){return CustomItemBase.Pin()-MakeNameWidget();}// 判断InColumnName,如果传入的是Value,就在价签的Value中添加价格if ((InColumnName.IsEqual(TEXT(Value)))){return CustomItemBase.Pin()-MakeValueWidget();}// 空widget用于占位return SNullWidget::NullWidget;
}//还是创建了一行两列streeview中的多个行还是需要在生成树的类中创建
void SMultiDetailTableRow::Construct(const FArguments InArgs, const TSharedRefSTableViewBase OwnerTableView,TSharedRefFCustomItemBase InCustomItemBase)
{//赋值保存CustomItemBase InCustomItemBase;//STableRow::FArguments()是这个是原生的风格样式,生成时的样式布局可替换STableRow::FArguments ParentArgs;ParentArgs.Padding(FMargin(0,8,0,0));//调用基类的构造函数,查看基类中的Construct方法SMultiColumnTableRow::Construct(ParentArgs, OwnerTableView);}数据子类
CustomItemBool
#pragma once
#include CustomItemBase.h//价签的子类父类中的价签已经印刷好了
class FCustomItemBool : public FCustomItemBase
{
public://创建后默认就是 falseFCustomItemBool():Value(false){}// 实现父类 CustomItemBase中的方法做具体的事即具体的名字具体的价格virtual TSharedRefSWidget MakeNameWidget() override;virtual TSharedRefSWidget MakeValueWidget() override;private:void OnCheckStateChanged(ECheckBoxState CheckState);ECheckBoxState GetCheckBoxState() const;bool Value;
};#include CustomItemBool.hTSharedRefSWidget FCustomItemBool::MakeNameWidget()
{//具体的名字Test Bool显示中文必须用Text包裹(TEXT(选中测试Bool)return SNew(STextBlock).Text(FText::FromString(TEXT(选中测试Bool)));
}TSharedRefSWidget FCustomItemBool::MakeValueWidget()
{//这里创建的是选择框可以是选择框、下拉框...Bool类的控件return SNew(SCheckBox)//绑定点击状态是否点击了,这是一个事件SLATE_EVENT( FOnCheckStateChanged, OnCheckStateChanged )//相当于点击了就触发点击事件将这个事件与回调函数OnCheckStateChanged绑定点击就触发.OnCheckStateChanged(this, FCustomItemBool::OnCheckStateChanged)//点击后的状态是选中了还是取消了查看SLATE_ATTRIBUTE( ECheckBoxState, IsChecked )后不是知道是啥//继续查看enum class ECheckBoxState : uint8里面有三种状态那这个IsChecked()的参数是不是就是要这个枚举//因为这里是绑定需要回调函数所以创建一个ECheckBoxState类型的函数试试结果懵对了.IsChecked(this, FCustomItemBool::GetCheckBoxState);
}void FCustomItemBool::OnCheckStateChanged(ECheckBoxState CheckState)
{//既然是回调函数那么当被触发后要做什么这个类是bool类型非真即假//使用三目运算符 给Value 赋值为 CheckState//CheckState的状态如果与ECheckBoxState::Checked 的状态相同就是真否则是假Value CheckState ECheckBoxState::Checked ? true : false;
}ECheckBoxState FCustomItemBool::GetCheckBoxState() const
{//上面已经给Value赋值了这里就问Value是什么如果是真就是 ECheckBoxState::Checked了否则。。。return Value? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}CustomItemInt
#pragma once
#include CustomItemBase.hclass FCustomItemInt : public FCustomItemBase
{
public:FCustomItemInt(): Value(0){}virtual TSharedRefSWidget MakeNameWidget() override;virtual TSharedRefSWidget MakeValueWidget() override;protected:void OnValueChanged(int32 InValue);int32 GetValue() const;
private:int32 Value;
};
#include CustomItemInt.h#include Widgets/Input/SSpinBox.hTSharedRefSWidget FCustomItemInt::MakeNameWidget()
{return SNew(STextBlock).Text(FText::FromString(TEXT(测试Int32)));
}TSharedRefSWidget FCustomItemInt::MakeValueWidget()
{return SNew(SBox).WidthOverride(200).MaxDesiredWidth(400).HAlign(HAlign_Fill).VAlign(VAlign_Fill)[SNew(SSpinBoxint32).OnValueChanged(this, FCustomItemInt::OnValueChanged).Value(this, FCustomItemInt::GetValue)];
}void FCustomItemInt::OnValueChanged(int32 InValue)
{Value InValue;
}int32 FCustomItemInt::GetValue() const
{return Value;
} streetview组装类
CustomDetailPlane
#pragma once
#include CustomItemBase.h//这里是使用typedef创建别名的方式用FCustomItemBase中的数据创建了一个树,
typedef STreeViewTSharedRefFCustomItemBase CustomDetailTreeView;class SCustomDetailPlane : public SCompoundWidget
{SLATE_BEGIN_ARGS(SCustomDetailPlane){}SLATE_END_ARGS()SCustomDetailPlane();virtual ~SCustomDetailPlane();void Construct(const FArguments InArgs);//树形结构中的行,这里就是一行一列这里可以再装入1行2列或是其他。。。TSharedRefITableRow CustomOnGenerateRow(TSharedRefFCustomItemBase Item,const TSharedRef STableViewBase TableView);//SLATE_EVENT( FOnGetChildren, OnGetChildren )//事件类型进一步查看API DECLARE_DELEGATE_TwoParams (FOnGetChildren,ArgumentType, TArrayArgumentType );//TwoParams表示需要两个参数,没有返回值,因为是GetChildren,ArgumentType应该是Children父类,然后从父类获取包含的子类void OnGetChildren(TSharedRefFCustomItemBase ParentItem, TArrayTSharedRefFCustomItemBase OutChildrens);//当CustomItemBool类创建好后这时已经在类中确定了要做的事这里创建一个函数用于给TreeItemSources赋值测试void SetItemData();private:TSharedPtrSWidgetSwitcher WidgetSwitcher;//这里用的是上面创建的别名生成指向STreeViewTSharedRefFCustomItemBase的指针//因为STreeViewTSharedRefFCustomItemBase太长所以使用别名也方便修改TSharedPtrCustomDetailTreeView OtherNameDetailTreeView;//树结构需要的数据源即已经准备好的价签展台已经准备好了需要几层就放入几个价签TArrayTSharedRefFCustomItemBase TreeItemSources;
};#include CustomDetailPlane.h#include CustomItemBool.h
#include Widgets/Layout/SWidgetSwitcher.hSCustomDetailPlane::SCustomDetailPlane()
{
}SCustomDetailPlane::~SCustomDetailPlane()
{
}void SCustomDetailPlane::Construct(const FArguments InArgs)
{ChildSlot[SAssignNew(WidgetSwitcher, SWidgetSwitcher) SWidgetSwitcher::Slot().HAlign(HAlign_Center).VAlign(VAlign_Center)[SNew(STextBlock).Text(FText::FromString(Custom Detail Plane))] SWidgetSwitcher::Slot().HAlign(HAlign_Fill).VAlign(VAlign_Fill)[//生成树控件只有树干SAssignNew(OtherNameDetailTreeView, CustomDetailTreeView)//设置数据源即准备好树枝.TreeItemsSource(TreeItemSources)//绑定代理将生成事件与实际生成方法绑定到一起.OnGenerateRow(this, SCustomDetailPlane::CustomOnGenerateRow)//绑定代理将获取事件与实际获取方法绑定到一起.OnGetChildren(this, SCustomDetailPlane::OnGetChildren)//生成列.HeaderRow(SNew(SHeaderRow) SHeaderRow::Column(Name).HeaderContentPadding(FMargin(0)).FillWidth(0.4f)[SNew(SBorder).Padding(FMargin(20, 5, 5, 5))[SNew(STextBlock).Text(FText::FromString(Name))]] SHeaderRow::Column(Value).HeaderContentPadding(FMargin(0)).FillWidth(0.6f)[SNew(SBorder).Padding(FMargin(20, 5, 5, 5))[SNew(STextBlock).Text(FText::FromString(Value))]])]];SetItemData();
}TSharedRefITableRow SCustomDetailPlane::CustomOnGenerateRow(TSharedRefFCustomItemBase Item,const TSharedRefSTableViewBase TableView)
{return SNew(SMultiDetailTableRow, TableView, Item);
}void SCustomDetailPlane::OnGetChildren(TSharedRefFCustomItemBase ParentItem,TArrayTSharedRefFCustomItemBase OutChildrens)
{ParentItem-GetChildrens(OutChildrens);
}void SCustomDetailPlane::SetItemData()
{//相当于实例化了一个FCustomItemBool类型的小控件BoolItem等待显示TSharedRefFCustomItemBool BoolItem MakeShareable(new FCustomItemBool());//在FCustomItemBool中已经将水果放到了果篮中并将果篮摆在了层板上这里将层板放到树上TreeItemSources.Add(BoolItem);//这里如果你又创建了新的控件就还用上面的MakeShareable(new FCustomItemBool());方法//然后用TreeItemSources.Add(BoolItem);添加//刷新OtherNameDetailTreeView-RequestTreeRefresh();//显示WidgetSwitcher的那一页WidgetSwitcher-SetActiveWidgetIndex(1);
}使用FProperty反射
使用FProperty反射用widget控件实时控制类中变量 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include GameFramework/Actor.h
#include ActorBase.generated.hUCLASS()
class CUSTOMWINDOW_API AActorBase : public AActor
{GENERATED_BODY()public:// Sets default values for this actors propertiesAActorBase();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public:// Called every framevirtual void Tick(float DeltaTime) override;protected:UPROPERTY(EditAnywhere, BlueprintReadOnly, SaveGame, meta(AllowedClasses), CategoryProActorBase)bool bIsSelect;UPROPERTY(EditAnywhere, BlueprintReadOnly, SaveGame, meta(AllowedClasses), CategoryProActorBase)FVector _Location;UPROPERTY(EditAnywhere, BlueprintReadOnly, SaveGame, meta(AllowedClasses), CategoryProActorBase)FVector _Scale;UPROPERTY(EditAnywhere, BlueprintReadOnly, SaveGame, meta(AllowedClasses), CategoryProActorBase)FRotator _Rotation;
};// Fill out your copyright notice in the Description page of Project Settings.#include ActorBase.h// Sets default values
AActorBase::AActorBase()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick true;
}// Called when the game starts or when spawned
void AActorBase::BeginPlay()
{Super::BeginPlay();}// Called every frame
void AActorBase::Tick(float DeltaTime)
{Super::Tick(DeltaTime);
} // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include ActorBase.h
#include TestActor.generated.hUCLASS()
class CUSTOMWINDOW_API ATestActor : public AActorBase
{GENERATED_BODY()public:// Sets default values for this actors propertiesATestActor();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public:// Called every framevirtual void Tick(float DeltaTime) override;UFUNCTION(BlueprintCallable, CategoryTestActor)void SetSelect(bool bInValue);UFUNCTION(BlueprintCallable, CategoryTestActor)void SetTestPropertChange(const FString InValue);UPROPERTY(EditAnywhere, BlueprintReadOnly, SaveGame, meta(AllowedClasses), CategoryProActorBase)int32 TestInt32 16;
};// Fill out your copyright notice in the Description page of Project Settings.#include TestActor.h// Sets default values
ATestActor::ATestActor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick true;
}// Called when the game starts or when spawned
void ATestActor::BeginPlay()
{Super::BeginPlay();}// Called every frame
void ATestActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);GEngine-AddOnScreenDebugMessage(1,2.f,FColor::Orange,FString::Printf(TEXT(bIsSelect %d TestInt32 %d),bIsSelect,TestInt32));
}void ATestActor::SetSelect(bool bInValue)
{
}void ATestActor::SetTestPropertChange(const FString InValue)
{
} ************
#pragma once
#include ActorBase.h// Item
class FTreeViewItemBase : public TSharedFromThisFTreeViewItemBase
{
protected:using Super FTreeViewItemBase;
public:FTreeViewItemBase(TWeakObjectPtrAActorBase InActorPtr,const FString PropertyName);virtual TSharedRefSWidget MakeNameWidget() 0;virtual TSharedRefSWidget MakeValueWidget() 0;virtual ~FTreeViewItemBase(){}void Getchildren(TArrayTSharedRefFTreeViewItemBase OutChildren) const{OutChildren Children;}
protected:TArrayTSharedRefFTreeViewItemBase Children;TWeakObjectPtrAActorBase ActorBasePtr;FProperty* PropertyPtr nullptr;
};// Row单行多列
class SMultiTableRow : public SMultiColumnTableRowTSharedRefFTreeViewItemBase
{SLATE_BEGIN_ARGS(SMultiTableRow){}SLATE_END_ARGS()virtual TSharedRefSWidget GenerateWidgetForColumn(const FName ColumnName) override;void Construct(const FArguments InArgs, const TSharedRefSTableViewBase InOwnerTableView, const TSharedRefFTreeViewItemBase InTreeViewItemBase);
private:TWeakPtrFTreeViewItemBase TreeViewItemBasePtr;
};
#include TreeViewItemBase.hFTreeViewItemBase::FTreeViewItemBase(TWeakObjectPtrAActorBase InActorPtr, const FString PropertyName): ActorBasePtr(InActorPtr)
{if (ActorBasePtr.IsValid()){PropertyPtr FindFPropertyFProperty(ActorBasePtr-GetClass(),*PropertyName);}
}TSharedRefSWidget SMultiTableRow::GenerateWidgetForColumn(const FName ColumnName)
{if (ColumnName.IsEqual((TEXT(Name)))){return TreeViewItemBasePtr.Pin()-MakeNameWidget();}if (ColumnName.IsEqual(TEXT(Value))){return TreeViewItemBasePtr.Pin()-MakeValueWidget(); }return SNullWidget::NullWidget;
}void SMultiTableRow::Construct(const FArguments InArgs, const TSharedRefSTableViewBase InOwnerTableView,const TSharedRefFTreeViewItemBase InTreeViewItemBase)
{TreeViewItemBasePtr InTreeViewItemBase;STableRow::FArguments ParentArgs;ParentArgs.Padding(FMargin(0,2,0,2));SMultiColumnTableRow::Construct(ParentArgs, InOwnerTableView);
}#pragma once
#include TreeViewItemBase.hclass FTreeViewItemBaseBool : public FTreeViewItemBase
{
public:FTreeViewItemBaseBool(TWeakObjectPtrAActorBase InActorPtr,const FString PropertyName): Super(InActorPtr,PropertyName){if (FBoolProperty* BoolProperty CastFieldFBoolProperty(PropertyPtr)){Value BoolProperty-ContainerPtrToValuePtrbool(InActorPtr.Get());}}virtual TSharedRefSWidget MakeNameWidget() override;virtual TSharedRefSWidget MakeValueWidget() override;private:void OnCheckStateChanged(ECheckBoxState CheckState);ECheckBoxState GetCheckBoxState() const;bool* Value nullptr;};#include TreeViewItemBaseBool.hTSharedRefSWidget FTreeViewItemBaseBool::MakeNameWidget()
{return SNew(STextBlock).Text(FText::FromString(TEXT(选中测试Bool)));
}TSharedRefSWidget FTreeViewItemBaseBool::MakeValueWidget()
{return SNew(SCheckBox).OnCheckStateChanged(this, FTreeViewItemBaseBool::OnCheckStateChanged).IsChecked(this, FTreeViewItemBaseBool::GetCheckBoxState);}void FTreeViewItemBaseBool::OnCheckStateChanged(ECheckBoxState CheckState)
{*Value CheckState ECheckBoxState::Checked ? true : false;
}ECheckBoxState FTreeViewItemBaseBool::GetCheckBoxState() const
{return *Value? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}#pragma once
#include TreeViewItemBase.hclass FTreeViewItemBaseNumber : public FTreeViewItemBase
{
public:FTreeViewItemBaseNumber(TWeakObjectPtrAActorBase InActorPtr,const FString PropertyName): Super(InActorPtr,PropertyName){if (PropertyPtr){Value PropertyPtr-ContainerPtrToValuePtrint32(InActorPtr.Get());}}virtual TSharedRefSWidget MakeNameWidget() override;virtual TSharedRefSWidget MakeValueWidget() override;protected:void OnValueChanged(int32 InValue);int32 GetValue() const;
private:int32* Value nullptr;
};#include TreeViewItemBaseNumber.h#include Widgets/Input/SSpinBox.hTSharedRefSWidget FTreeViewItemBaseNumber::MakeNameWidget()
{return SNew(STextBlock).Text(FText::FromString(TEXT(测试Int32)));
}TSharedRefSWidget FTreeViewItemBaseNumber::MakeValueWidget()
{return SNew(SBox).WidthOverride(200).MaxDesiredWidth(400).HAlign(HAlign_Fill).VAlign(VAlign_Fill)[SNew(SSpinBoxint32).OnValueChanged(this, FTreeViewItemBaseNumber::OnValueChanged).Value(this, FTreeViewItemBaseNumber::GetValue)];
}void FTreeViewItemBaseNumber::OnValueChanged(int32 InValue)
{*Value InValue;
}int32 FTreeViewItemBaseNumber::GetValue() const
{return *Value;
}*****************************
#pragma once
#include TreeViewItemBase.hclass SDetailTabWidget : public SCompoundWidget
{SLATE_BEGIN_ARGS(SDetailTabWidget){}SLATE_END_ARGS()void Construct(const FArguments InArgs);private:TSharedPtrSWidgetSwitcher WidgetSwitcher;TSharedPtrSTreeViewTSharedRefFTreeViewItemBase TreeViewItem;TArrayTSharedRefFTreeViewItemBase TreeViewSource;public:TSharedRefclass ITableRow GenerateTreeViewRow(TSharedRefFTreeViewItemBase ItemBase, const TSharedRef class STableViewBase TableViewBase);void OnGetChildren(TSharedRefFTreeViewItemBase ItemBase, TArrayTSharedRefFTreeViewItemBase OutChildren);void SetItemData();
};#include DetailTabWidget.h#include TestActor.h
#include TreeViewItemBaseBool.h
#include TreeViewItemBaseNumber.h
#include Kismet/GameplayStatics.h
#include Widgets/Layout/SWidgetSwitcher.hvoid SDetailTabWidget::Construct(const FArguments InArgs)
{ChildSlot[SAssignNew(WidgetSwitcher, SWidgetSwitcher) SWidgetSwitcher::Slot().HAlign(HAlign_Center).VAlign(VAlign_Center)[SNew(STextBlock).Text(FText::FromString(This DetailTab Panel))] SWidgetSwitcher::Slot().HAlign(HAlign_Fill).VAlign(VAlign_Fill)[SAssignNew(TreeViewItem, STreeViewTSharedRefFTreeViewItemBase).TreeItemsSource(TreeViewSource)//委托生成每一行绑定自定义方法事件触发时生成.OnGenerateRow(this,SDetailTabWidget::GenerateTreeViewRow).OnGetChildren(this,SDetailTabWidget::OnGetChildren).HeaderRow(SNew(SHeaderRow) SHeaderRow::Column(Name).HeaderContentPadding(FMargin(0, 0, 0, 0)).FillWidth(0.4f)[SNew(SBorder).Padding(FMargin(10, 5, 5, 5))[SNew(STextBlock).Text(FText::FromString(TEXT(名 称)))]] SHeaderRow::Column(Value).HeaderContentPadding(FMargin(0, 0, 0, 0)).FillWidth(0.4f)[SNew(SBorder).Padding(FMargin(10, 5, 5, 5))[SNew(STextBlock).Text(FText::FromString(TEXT(属 性)))]])]];SetItemData();
}TSharedRefclass ITableRow SDetailTabWidget::GenerateTreeViewRow(TSharedRefFTreeViewItemBase ItemBase,const TSharedRefclass STableViewBase TableViewBase)
{return SNew(SMultiTableRow, TableViewBase, ItemBase);
}void SDetailTabWidget::OnGetChildren(TSharedRefFTreeViewItemBase ItemBase,TArrayTSharedRefFTreeViewItemBase OutChildren)
{ItemBase-Getchildren(OutChildren);
}void SDetailTabWidget::SetItemData()
{UWorld* World GWorld-GetWorld();AActor* FindAcr UGameplayStatics::GetActorOfClass(World, ATestActor::StaticClass());//这里需要注意TestActor必须放置在场景中否则运行崩溃 if (AActorBase* ActorBase CastAActorBase(FindAcr)){TSharedRefFTreeViewItemBaseBool BoolItem MakeShareable(new FTreeViewItemBaseBool(ActorBase,bIsSelect ));TreeViewSource.Add(BoolItem);TSharedRefFTreeViewItemBaseNumber NumberItem MakeShareable(new FTreeViewItemBaseNumber(ActorBase,TestInt32));TreeViewSource.Add(NumberItem);TreeViewItem-RequestTreeRefresh();WidgetSwitcher-SetActiveWidgetIndex(1);}
} 文章转载自: http://www.morning.glkhx.cn.gov.cn.glkhx.cn http://www.morning.qgwdc.cn.gov.cn.qgwdc.cn http://www.morning.zrpys.cn.gov.cn.zrpys.cn http://www.morning.dsgdt.cn.gov.cn.dsgdt.cn http://www.morning.mlnbd.cn.gov.cn.mlnbd.cn http://www.morning.scjtr.cn.gov.cn.scjtr.cn http://www.morning.rxfbf.cn.gov.cn.rxfbf.cn http://www.morning.ghxzd.cn.gov.cn.ghxzd.cn http://www.morning.nmrtb.cn.gov.cn.nmrtb.cn http://www.morning.dzyxr.cn.gov.cn.dzyxr.cn http://www.morning.ypzr.cn.gov.cn.ypzr.cn http://www.morning.ktmbr.cn.gov.cn.ktmbr.cn http://www.morning.tbqxh.cn.gov.cn.tbqxh.cn http://www.morning.swyr.cn.gov.cn.swyr.cn http://www.morning.qlxgc.cn.gov.cn.qlxgc.cn http://www.morning.qhnmj.cn.gov.cn.qhnmj.cn http://www.morning.rdlfk.cn.gov.cn.rdlfk.cn http://www.morning.vtbtje.cn.gov.cn.vtbtje.cn http://www.morning.dqxnd.cn.gov.cn.dqxnd.cn http://www.morning.ryfqj.cn.gov.cn.ryfqj.cn http://www.morning.qlxgc.cn.gov.cn.qlxgc.cn http://www.morning.rpjr.cn.gov.cn.rpjr.cn http://www.morning.qrqcr.cn.gov.cn.qrqcr.cn http://www.morning.fdlyh.cn.gov.cn.fdlyh.cn http://www.morning.trzzm.cn.gov.cn.trzzm.cn http://www.morning.iiunion.com.gov.cn.iiunion.com http://www.morning.ltkzb.cn.gov.cn.ltkzb.cn http://www.morning.jkrrg.cn.gov.cn.jkrrg.cn http://www.morning.lhrcr.cn.gov.cn.lhrcr.cn http://www.morning.fwdln.cn.gov.cn.fwdln.cn http://www.morning.wkrkb.cn.gov.cn.wkrkb.cn http://www.morning.qfdmh.cn.gov.cn.qfdmh.cn http://www.morning.xhklb.cn.gov.cn.xhklb.cn http://www.morning.xirfr.cn.gov.cn.xirfr.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.mbaiwan.com.gov.cn.mbaiwan.com http://www.morning.zrks.cn.gov.cn.zrks.cn http://www.morning.kxwsn.cn.gov.cn.kxwsn.cn http://www.morning.fhqdb.cn.gov.cn.fhqdb.cn http://www.morning.qllcm.cn.gov.cn.qllcm.cn http://www.morning.nwrzf.cn.gov.cn.nwrzf.cn http://www.morning.rkhhl.cn.gov.cn.rkhhl.cn http://www.morning.mkrjf.cn.gov.cn.mkrjf.cn http://www.morning.wjplr.cn.gov.cn.wjplr.cn http://www.morning.bprsd.cn.gov.cn.bprsd.cn http://www.morning.fbpdp.cn.gov.cn.fbpdp.cn http://www.morning.jtfcd.cn.gov.cn.jtfcd.cn http://www.morning.wtcbl.cn.gov.cn.wtcbl.cn http://www.morning.dfwkn.cn.gov.cn.dfwkn.cn http://www.morning.brnwc.cn.gov.cn.brnwc.cn http://www.morning.czgfn.cn.gov.cn.czgfn.cn http://www.morning.pmtky.cn.gov.cn.pmtky.cn http://www.morning.trlhc.cn.gov.cn.trlhc.cn http://www.morning.cbchz.cn.gov.cn.cbchz.cn http://www.morning.ltrz.cn.gov.cn.ltrz.cn http://www.morning.bbtn.cn.gov.cn.bbtn.cn http://www.morning.rmxgk.cn.gov.cn.rmxgk.cn http://www.morning.thxfn.cn.gov.cn.thxfn.cn http://www.morning.bpwfr.cn.gov.cn.bpwfr.cn http://www.morning.kjyhh.cn.gov.cn.kjyhh.cn http://www.morning.gqdsm.cn.gov.cn.gqdsm.cn http://www.morning.qgjxt.cn.gov.cn.qgjxt.cn http://www.morning.tlnkz.cn.gov.cn.tlnkz.cn http://www.morning.rxhs.cn.gov.cn.rxhs.cn http://www.morning.thntp.cn.gov.cn.thntp.cn http://www.morning.qfkxj.cn.gov.cn.qfkxj.cn http://www.morning.zfyr.cn.gov.cn.zfyr.cn http://www.morning.shawls.com.cn.gov.cn.shawls.com.cn http://www.morning.kqxng.cn.gov.cn.kqxng.cn http://www.morning.tbplf.cn.gov.cn.tbplf.cn http://www.morning.jqtb.cn.gov.cn.jqtb.cn http://www.morning.fflnw.cn.gov.cn.fflnw.cn http://www.morning.sbjbs.cn.gov.cn.sbjbs.cn http://www.morning.rqqkc.cn.gov.cn.rqqkc.cn http://www.morning.myzfz.com.gov.cn.myzfz.com http://www.morning.dbcw.cn.gov.cn.dbcw.cn http://www.morning.mcqhb.cn.gov.cn.mcqhb.cn http://www.morning.clpkp.cn.gov.cn.clpkp.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.ztcwp.cn.gov.cn.ztcwp.cn