Godot Version
4.4.1
Question
I am creating an app to facilitate character creation for a ttrpg I made for my friends. Within, they must select 4 of 28 skills. I figured the easiest way to do this would be 28 toggle buttons, then get signals from each and interpret only I can’t seem to find a way to actually tell which buttons are toggled or not.
I tried using a for loop to bind each button to a signal, but could not figure out how to get information out of that other than if the signal was true or false.
@export var index:RichTextLabel
@export var button_container:VBoxContainer
var testtext: String = "test"
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
for i in button_container.get_children():
for button in i.get_children():
if button is Button:
print(button.get_name())
button.toggled.connect(_on_button_toggled)
pass # Replace with function body.
func _on_button_toggled(button_name) -> void:
if button_name.get_name() == "Harmor":
testtext = str(button_name.get_name())
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
index.text = str(testtext)
pass
Hi,
You could add a class for each button that has its own signal. That signal being a custom one, you can add any parameter to it, including the button itself.
The code would look like this:
On each button:
class_name CharacterButton
extends Button
# Here, add any useful info for each button so that
# you can set them in the Inspector and read them afterward.
signal clicked(button: CharacterButton)
func _ready():
self.clicked.connect(on_clicked)
func on_clicked():
clicked.emit(self)
And on your script, updated:
extends Control
@export var index: RichTextLabel
@export var button_container: VBoxContainer
func _ready() -> void:
for i in button_container.get_children():
for button in i.get_children():
# Here I'm using my custom CharacterButton type.
if button is CharacterButton:
button.clicked.connect(_on_button_clicked)
func _on_button_clicked(button: CharacterButton) -> void:
print(button.name)
# Here, use the button parameter to read any info from it.
What’s important here is the clicked.emit(self) line: basically, instead of emitting a click signal without parameter, buttons will emit a click signal with themselves as a parameter. self refers to the script instance the signal is called from.
Let me know if that helps.
1 Like
Loop through buttons and check their button_pressed property.
Alternatively, if you want to keep 4 buttons pressed and automatically un-press the earliest pressed button, keep a queue of pressed buttons. When a new signal arrives, if the button that sent it is already in the queue, don’t add it, otherwise push it at the end of queue. When the queue size goes to 5, pop the button from the start of queue. The queue can be implemented as an array.
As for identifying buttons in the signal handler, when connecting you can simply bind a signal argument that contains the button reference. That way you don’t need to add any additional scripts to buttons :
button.toggled.connect(_on_button_toggled.bind(button))
Is this not something ButtonGroup should work well with?
Button group only allows for s single button to be pressed.
You’re right - I misunderstood the question. 
Thank you everyone! I ended up doing a mix of both suggestions, with one caveat that for Sixrobins solution, I had to make a small change to the code because I am using toggle buttons and not normal buttons.
func _ready():
self.clicked.connect(on_clicked)
became
func _ready():
self.pressed.connect(on_clicked)