Plugin, add Snew button to Snew box after being created?

Hey guys,

I’m new to code and am getting a little stuck on some basics here, as extensive googling wont help.

I would like to dynamically populate a floating plugin menu with buttons for each loop out of an array.
Most is working, but im failing to let an already created button add a new button to the menu.

How would you reference or do this? is it possible to add to a scrollbox that is created as SNew?

Thank you
Rens

TSharedRef<SDockTab> FConsoleModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{

FText WidgetText = FText::Format(
	LOCTEXT("WindowWidgetText", "Add code to {0} in {1} to override this window's contents"),
	FText::FromString(TEXT("FConsoleModule::OnSpawnPluginTab")),
	FText::FromString(TEXT("Console.cpp"))
	);

return SNew(SDockTab)
	.TabRole(ETabRole::NomadTab)

////// PERSONAL CODE V

		SNew(SScrollBox)
		+   SScrollBox::Slot().Padding(10, 5)
		
	
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot().FillWidth(2)

	
		SNew(SButton)
		.Text(FText::FromString(TEXT("Load Commands")))
		.OnClicked_Lambda(&]()-&gt;FReply

{
	FString ConsoleCommand = FString("r.shadowquality 0");
	CommandCollection.Add(ConsoleCommand);
	const TCHAR* Command = *ConsoleCommand;

	GEngine-&gt;Exec(NULL, Command, *GLog);


	for (const auto& Item : CommandCollection)
	{
					
		// GET SCROLLBOX TO ADD NEW SLOT + BUTTON??
		
	}
	
	return FReply::Handled(); })
	
	]

Micheal Noland gave me some pointers,
It is almost working, but wanted to post before getting some sleep in case someone reads it,
It loads and adds buttons now, but the manual reload crashes the editor if I were to use the Lambda.
Also need to fix a warning "declaration hides in class member because the strings are higher up…

TSharedRef<SDockTab> FConsoleModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{

FText WidgetText = FText::Format(
	LOCTEXT("WindowWidgetText", "Add code to {0} in {1} to override this window's contents"),
	FText::FromString(TEXT("FConsoleModule::OnSpawnPluginTab")),
	FText::FromString(TEXT("Console.cpp"))
	);

TSharedRef&lt;SVerticalBox&gt; ButtonList = SNew(SVerticalBox);

FString ButtonName = FString("asdf");
FString ConsoleCommand = FString("r.shadowquality 0");

CommandCollection.Add(ConsoleCommand);
CommandCollection.Add(ButtonName);

//	FString SaveDirectory = FString("C:/Users/Chief/Desktop/Newfolder");
//	FString FileName = FString("command.txt");
//	FString TextToSave = ConsoleCommand;
//	FString AbsoluteFilePath = SaveDirectory + "/" + FileName;
//	FFileHelper::SaveStringToFile(TextToSave, *AbsoluteFilePath);
//	const TCHAR* Command = *ConsoleCommand;

//	GEngine-&gt;Exec(NULL, Command, *GLog);


for (const auto& Item : CommandCollection)
{

	ButtonList-&gt;AddSlot()
		// Fix Buttonheight
		
			SNew(SButton)
			.Text(FText::FromString(TEXT("Load Commands")))

		];

}

ButtonList-&gt;AddSlot()


	SNew(SScrollBox)
	+ SScrollBox::Slot().Padding(10, 5)

	
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot().FillWidth(2)

	
		SNew(SButton)
		.Text(FText::FromString(TEXT("Load Commands")))
		.OnClicked_Lambda(&]()-&gt;FReply
{

// CRASHES EDITOR.

//	ButtonList-&gt;AddSlot()
//		
//			SNew(SButton)
//		];

	return FReply::Handled(); })

	]]];

return SNew(SDockTab)
	.TabRole(ETabRole::NomadTab)
	
	
		ButtonList
	];

}

It crashes because your lambda captures a local variable by reference, which has gone out of scope by the time the lambda is executed. Using default capture by reference (=]) is dangerous and best avoided. What you want to do is capture the smart pointer by value (it’s still a pointer so won’t copy the actual widget). The following should do it:


.OnClicked_Lambda([ButtonList]()->FReply

fantastic! made me understand a lot more about the Lambda function.

Really happy to get it a lot further, still got a problem with the second Lambda,
It is supposed to pick up the variable String that gets loaded in from a text file, the name of the button does pick it up, but to transfer it as a const TCHAR seems to be a struggle.

Also, when pressing the load button it cleared the array and then repopulated it, that worked before but is now broken… though its not a big issue.

Thanks you for the help!

Capture it as an FString instead - [ConsoleCommand].
As it is you have the same issue you had before, only a bit more subtle. You’re copying a pointer, which points to heap memory controlled by a local variable, so the memory is released before the lambda gets called.

If by clearing the array you mean the list of buttons, just call ButtonList->ClearChildren(); before your loop.

Though lambdas can work, generally when they get large/nested, it’s more manageable to bind your Slate events to member functions instead, and store the data you were capturing as class members.

This for sure is a great puzzle to learn more about code with,
I invested time googling member functions before but had problems figuring out how slate and all of it works, hence its all cramped into one lambda.
Will spend some more time trying to figure out how to build it cleaner after everything.

I cleared the array thinking it would not add everything twice but forgot the buttonlist also needed the same.

As for the ConsoleCommand, being a string, the lambda complains that there is no suitable conversion from const Fstring to const TCHAR,
Not sure if my Fstring just needs to be a const, or if the structure of my lambda makes it so it requires a TCHAR, ill try and research some more.

Thank you

I doubt it’s the lambda complaining. You probably just need to pass *ConsoleCommand to the Exec call.

adding * worked like a charm.
thank you for all the help