x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

AnswerHub Maintenance

Background maintenance is scheduled to occur between 9 - 11am EDT on Tuesday, May 21. Site operation may be slower than normal during this time and a brief interruption in operation may be observed

Bind OnClicked Events to buttons created at runtime.

Hello Everyone ,

I have scrollbox with buttons created at runtime based on number of .sav files in game folder.

 UButton *save_button = NewObject<UButton>(this);
 loadgame_scrollbox->AddChild(save_button);

Each button represents one save file, that can be loaded. I'm trying to bind events to that buttons at runtime:

 button_interface->OnClicked.AddDynamic(this, &UMasterUI_Menu::OnClick_button_load_game);

This code works, but it's bad idea to repeat it 100 times with 100 functions (one per button). And I don't know how many buttons will spawn, it's based on number of .sav files. I don't know which button called that function so I don't know which save file should I load!

Is it possible to return Name/Index of the clicked button with OnClicked? And then use that index in OnClick_button_load_game(int32 index) function to determine which button was clicked. For example OnValueChanged Event returns float Value by default(USlider) and it's easy to access Value this way.

I need c++ solution, not BP (i'm using c++ only).

Product Version: UE 4.8
Tags:
more ▼

asked Aug 08 '15 at 12:33 PM in C++ Programming

avatar image

XadE
55 3 5 8

(comments are locked)
10|2000 characters needed characters left

3 answers: sort voted first

Header File

 #pragma once
 
 #include "Components/Button.h"
 #include "DemoButton.generated.h"
 
 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLoadDelegate, FString, name);
 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FClickDelegate);
 
 UCLASS()
 class FPS4_8_API UDemoButton : public UButton
 {
     GENERATED_BODY()
 
 public:
     UDemoButton();
 
     UPROPERTY()
     FLoadDelegate load;
     
     UPROPERTY()
     FClickDelegate click;
 
     void OnClick();
 
     void LoadGameFile(FString name);
 };

Source file

 #include "FPS4_8.h"
 #include "DemoButton.h"
 
 UDemoButton::UDemoButton()
 {
     OnClicked.AddDynamic(this, &UDemoButton::OnClick);
     
     //Bind function
     load.AddDynamic(this,&UDemoButton::LoadGameFile);
 }
 
 void UDemoButton::OnClick()
 {
     load.Broadcast(this->GetName());
 }
 
 void UDemoButton::LoadGameFile(FString name)
 {
     /** load stuff here **/
 }


So each button has his delegate and when you clicked, it will fire up.

You could also make a delegate that return stuff from your button and after call the load delegate from these info.

Is that help you more ?

If not just tell me.

gamer08

more ▼

answered Aug 09 '15 at 06:03 PM

avatar image

gamer08
266 17 17 36

avatar image XadE Aug 09 '15 at 06:17 PM

load.Broadcast(this->GetName());

I can't test that today, so I have one more question. This line returns Name of clicked button and sends Name to loadgame function, right?

avatar image gamer08 Aug 09 '15 at 07:46 PM

This->GetName return the button name and load.Broadcast fire the delegate attach to load. In this case this is loadGameFile.

So short answer, yes you're right !

Remember, you can attach any functions you want to your delegate (even a function from another class) as long as you can have access to it and it respect the function signature.

If you have any problems or questions, just tell me.

gamer08

avatar image XadE Aug 09 '15 at 08:58 PM

Thank you for everything!

XadE

avatar image Syntopia May 24 '17 at 02:50 PM

Forgot UFUNCTION() over OnClick and LoadGameFile, it works thanks!

(comments are locked)
10|2000 characters needed characters left

Hello XadE,

Well what you could try, even if it's not beautiful, you can wrap a level of indirection on your OnClicked delegate. What I mean by that, you define a new type of delegate that return a value. this new type will do an internal invoke to your another delegate that will call your function load_save.

With that level of indirection you'll be able to catch the actor the Onclicked came from.

Do you follow me?

gamer08

more ▼

answered Aug 08 '15 at 03:42 PM

avatar image

gamer08
266 17 17 36

avatar image XadE Aug 08 '15 at 04:24 PM

Sounds good, could you explain how to do that in code?

(comments are locked)
10|2000 characters needed characters left

Hello again XadE, I made an example for you to understand.

Header file

 #pragma once
 
 #include "GameFramework/Volume.h"
 #include "GameFramework/Actor.h"
 #include "DemoDelegateVolume.generated.h"
 
 DECLARE_DELEGATE_OneParam(HelloDelegate, FString);
 
 UCLASS()
 class FPS4_8_API ADemoDelegateVolume : public AVolume
 {
     GENERATED_BODY()
     
 public:
     ADemoDelegateVolume();
     
     UFUNCTION()
     void OnBeginOverlap(AActor* overlappingActor);
 
     void HelloFromCharacter(FString characterNmae);
 
     HelloDelegate hello;
 };


Source file

     #include "FPS4_8.h"
     #include "DemoDelegateVolume.h"
     #include "Engine.h"
     #include "FPS4_8Character.h"
     
     ADemoDelegateVolume::ADemoDelegateVolume()
     {
         
         OnActorBeginOverlap.AddDynamic(this, &ADemoDelegateVolume::OnBeginOverlap);
         
         //Bind function
         hello.BindUObject(this, &ADemoDelegateVolume::HelloFromCharacter);
     }
     
     void ADemoDelegateVolume::OnBeginOverlap(AActor* overlappingActor)
     {
         AFPS4_8Character* character = Cast<AFPS4_8Character>(overlappingActor);
         if (character)
         {
             hello.Execute(overlappingActor->GetName());
         }
     }
     
     void ADemoDelegateVolume::HelloFromCharacter(FString characterName)
     {
         if (GEngine)
             GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString("Hello from character : ").Append(characterName));
     
     }

Now some details.

I did based on a volume.

I defined a new BeginOverlap that I replace the default one with. (maybe not required in your case).

I define a delegate with one parameter in my case a FName.

I'm a delegate instance on my volume to use it.

In my volume constructor I replace the OnOverlap function with my own with the addDynamic macro.

After that I bind the delegate instance to the function with 1 parameter I want ( in your case it will be OnClick_button_load_game with the parameter you want)

After on my own BeginOverlap, I invoke my delegate bind to the function with one parameter as you can see.

For more infos on delegate you can here : Delegate doc

Is my example help you ?

If not, or if you need anything, just tell me.

gamer08 .

more ▼

answered Aug 08 '15 at 08:18 PM

avatar image

gamer08
266 17 17 36

avatar image XadE Aug 08 '15 at 08:46 PM

Thank you. I'll test this code tomorrow

avatar image XadE Aug 09 '15 at 11:12 AM

It works on events like that:

alt text

but OnClicked doesn't return anything.

alt text

 void UMasterUI_Menu::OnButtonClicked()  //same for all buttons, binded inside while loop at runtime
 {
     testdelegate.Execute(/*still no idea how i can get clicked button here*/);
 }


Please, help me. Maybe there is another way of doing that.

avatar image gamer08 Aug 09 '15 at 12:55 PM

Hello XadE,

I have a little question for you, did you made your menu scrollBox in slate code or with blueprints directly?

if so, did you declared a custom class for your buttons in code?

such as

 UCLASS()
 
 class LoadButton : public UButton
 {
 
 /****/
 /****/
 
 };

Depending on your answers, I have different solutions for you.

gamer08

avatar image XadE Aug 09 '15 at 01:04 PM

Hello gamer08,

For now it's simple UScrollBox with UButtons spawned in c++ code(default class). I have widget blueprint too, with some panel widgets (it's easier to make good menu design here).

avatar image gamer08 Aug 09 '15 at 01:23 PM

Ok thanks for that info, what I propose you is to create your own UButton subclass (that contains slate stuff) so you will be able to define your delegate attach to the Onclicked Event on your button and with that method, you'll be able to catch the infos you need and use the code I shown you.

Did you follow me ?

I could also make an example for you if you need (with button this time to stick to your problem)

Just tell me, always glad to help.

gamer08

avatar image XadE Aug 09 '15 at 01:33 PM

Hello gamer08,

Could you make an example? Thank you for response

avatar image gamer08 Aug 09 '15 at 01:39 PM

Ok i'll do it, give me some time.

gamer08

avatar image gamer08 Aug 09 '15 at 03:11 PM

Hello, i'm building your example and I wanna know your UMasterUI_Menu is a custom class you made?

What's the type of it? I just want to know a bit of your achitecture to stick as most as possible on your situation.

For the moment I builded a custom UserWidget that has a ScrollBox but before going any further, I'd like to know your actual architecture related to your UI.

Thanks

gamer08

avatar image XadE Aug 09 '15 at 03:57 PM

It's custom UUserWidget

avatar image gamer08 Aug 09 '15 at 04:16 PM

Did you put your UMasterUI_Menu on the gameMode, a customHUD or elsewhere?

Also can you send me a partial header and source (all I want, it's your constructor and the init) of your UMasterUI_Menu. My example is a bit fuzzy and Don't want to lost you. If you don't want, I'll explain the best I can.

thanks gamer08

avatar image XadE Aug 09 '15 at 04:23 PM
 UCLASS()
 class EASSETH_API UMasterUI_Menu : public UUserWidget

It's parent class of my widget blueprint which I add to viewport on BeginPlay of my menu pawn.

 void UMasterUI_Menu::NativeConstruct()
 {
     Super::NativeConstruct();
 
     menuPhase = EMenuPhaseEnum::VE_Menu;
 
     MasterUI_Construct();
 }

MasterUI_Construct - i use this function to read game video/audio settings from .sav and get +-10 widgets from widget blueprint (GetWidgetFromName).

avatar image gamer08 Aug 09 '15 at 04:30 PM

Thanks for sharing, i'll be back soon

avatar image XadE Aug 09 '15 at 04:38 PM

It's my prototype function that spawns buttons.

Thanks, XadE

avatar image gamer08 Aug 09 '15 at 05:35 PM

my class exemple is almost done and now I've spotted the problem.

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question