0 votes

I wanted to create a button thas is created in code, but to make it interactive a signal has to be connected wit the .connect function.

I got it working regular as follows:

func _ready():
self.connect("pressed", self, "_on_Button_pressed")

func _on_Button_pressed():
self.text = "OK"

But i want to use it in a class, but then it is not working.

class CreateButton:

var newButton : Button

func _init(_parent, _text)->void:
    newButton = Button.new()
    newButton.text = _text
    newButton.connect("pressed", self, "_on_Button_pressed")
    _parent.add_child(newButton)


func _on_Button_pressed():
    newButton.text = "OK"

Any help is welkom!

asked Mar 16 in Engine by PepijnWe (36 points)

Your class declaration looks fine, but how are you using it? Can you show the code where you instanciate CreateButton?
Also, what do you mean by "It's not working"? The button doesn't show up? Or is it not doing anything when clicked?

It creates a button, but the interactive part is not working.
Specificly this section of the code is not running:

func _on_Button_pressed():
newButton.text = "OK"

This is where the function is called

#Displayes list buttons in Grid container Carlist
func displayList(_car):
for i in _car:
    #creates Button option
    GameData.CreateButton.new(Carlist, "BUY")

2 Answers

0 votes
Best answer

With the help of Zylann and my roommate i figured it out if anyone has the same issue

This is the class:

class CreateButton:

var newButton : Button

func _init(_parent, _text):
    newButton = Button.new()
    newButton.text = _text
    newButton.connect("pressed", self, "_on_Button_pressed")
    _parent.add_child(newButton)

func _on_Button_pressed():
    newButton.text = "OK"

And this is how to call it:

#List of buttons used in the displayList function
var Buttons = []

#Displayes list buttons in Grid container Carlist
func displayList(_car):
    for i in _car:
        #creates Button option
        Buttons.insert(i, GameData.CreateButton.new(Carlist, "BUY"))
answered Mar 23 by PepijnWe (36 points)

The buttons need to be saved to be able to use the signal

+1 vote

Connections appear to keep weak references to the listener objects they target.

You are instancing a class which connects to a button, however you are not storing the instance anywhere. So as soon as it gets out of scope of the function where you created it, the instance will be destroyed. And with it, the connection it had.

Storing the instance of CreateButton somewhere, like a member variable, makes it work.

answered Mar 16 by Zylann (26,143 points)

The button stays active after creation and is stored in the Carlist grid container?,
do you have a link to an example if i did it wrong?

I'm referring to your custom class, CreateButton.

    #creates Button option
    GameData.CreateButton.new(Carlist, "BUY")

This creates an instance of CreateButton, but it gets immediately dropped because you are not storing it anywhere.

This is how you'd need to fix it:

var create_button

#Displayes list buttons in Grid container Carlist
func displayList(_car):
    for i in _car:
        #creates Button option
        create_button = GameData.CreateButton.new(Carlist, "BUY")

However I find it a bit awkward, not sure what your goal is when using such class.

Im trying to create a buy menu with usable buy buttons, the class is used to make the buttons flexible. I can for example create a Sell button with the same class

This is what my goal is

btw the suggested code does not work, i think because the var create_button gets overwritten each time the for loop calls it

Yeah sorry, but I hope you get the idea though. In this case it'd have to be an array, but then it gets even more awkward. I start to see what you try to do though, and I think there is a more elegant way.

You can add bindings to a connection, like so:

func displayList(_car):
    for i in _car:
        newButton = Button.new()
        newButton.text = "BUY"
        newButton.connect("pressed", self, "_on_Button_pressed", [newButton])
        add_child(new_button)

func _on_Button_pressed(button):
    button.text = "OK"

What you put in those bindings will be added to the arguments of the function.
Then you don't need an extra class or ways to somehow maintain its references.

This is working, like i had it before but then i tried to implement it as an class. If i want to add another button for example i need to copy and paste this code, using a class can simplyfy this process, i will look futher in to this tomorrow. Thanks for your time so far!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.