I want to pass a parameter back with a button press. The below method worked under Godot 3.5:
description_button_node.connect("pressed", self, "_OnTechnologyDescription_pressed", [param1])
under Godot 4 it throws the following error
Invalid call to function 'connect' in base 'Button'. Expected 3 arguments.
any ideas out there?
passing a parameter on a Button .connect signal in Godot 4.2
- Edited
grymjack you call connect
on the signal
.
dbutton.pressed.connect(techdesp)
For passing params use bind
on the callable (function):
dbutton.pressed.connect(techdesp.bind(param1))
- Edited
grymjack https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html#custom-signals
Maybe try creating custom signal, then when button is pressed you custom_signal.emit(my_value)
For me this approach is easier to read and undestand
kuligs2 I am creating on 'on the fly' flowchart tree (technology/science abilities) based on values in a database. A generic '?' button is placed in all the different flow chart item types that the user could press to open documentation on that position in the chart. I wanted to create a parameter that would be sent back with the button press that would identify the item in the flowchart the user was clicking on.
Jesusemora this is what I ended up doing
button_element.connect("pressed", func(): self._OnScienceDescription_pressed(scienceid_element.text))
Jesusemora's answer is the correct one.
The manual has the same example:
https://docs.godotengine.org/en/4.2/classes/class_signal.html#method-descriptions
- Edited
- Best Answerset by grymjack
grymjack if you would like some advice: avoid lambdas, they make your code messy and hard to read. create a function in the main script and call it from there or pass a callable.
also, don't put callables between ""
s, you will mistype a letter and cause the game to crash.
grymjack
button_element.connect("pressed", func(): self._OnScienceDescription_pressed(scienceid_element.text))
don't do this.
do:
button_element.pressed.connect(_OnScienceDescriptor_pressed.bind(scienceid_element.text))
it's the clearer form and the way it's done in godot 4.
Jesusemora avoid lambdas, they make your code messy and hard to read. create a function in the main script and call it from there or pass a callable.
Don't see how lambdas make code messy. A lambda and a regular method look exactly the same in the code but with lambdas you get the added benefit of closure. This can make code shorter and less convoluted in many cases.
xyz Don't see how lambdas make code messy.
because you are writing a function horizontally on an indentation language, it breaks the style and it's difficult to tell where the function begins and where it ends.
They are (arguably) ok in languages with semicolons and brackets, but not in gdscript where we use end-of-lines to break code.
Maybe I confused "lambdas" from other languages with how they work in gdscript. What I meant was, functions written horizontally or as parameters of another function.
In the gdscript style guide there are some rules that would be broken by the usage of lambdas inside parentheses:
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html
Line length¶
Keep individual lines of code under 100 characters.
If you can, try to keep lines under 80 characters. This helps to read the code on small displays and with two scripts opened side-by-side in an external text editor. For example, when looking at a differential revision.
One statement per line¶
Never combine multiple statements on a single line. No, C programmers, not even with a single line conditional statement.
Format multiline statements for readability¶
When you have particularly long if statements or nested ternary expressions, wrapping them over multiple lines improves readability. Since continuation lines are still part of the same expression, 2 indent levels should be used instead of one.
GDScript allows wrapping statements using multiple lines using parentheses or backslashes. Parentheses are favored in this style guide since they make for easier refactoring. With backslashes, you have to ensure that the last line never contains a backslash at the end. With parentheses, you don't have to worry about the last line having a backslash at the end.
When wrapping a conditional expression over multiple lines, the and/or keywords should be placed at the beginning of the line continuation, not at the end of the previous line.
this line has 101 characters, I counted them, but I could tell from a glance that it begins to get too long:
button_element.connect("pressed", func(): self._OnScienceDescription_pressed(scienceid_element.text))
It would probably look cleaner if the lambda is defined beforehand:
var lambda = func():
self._OnScienceDescription_pressed(scienceid_element.text)
button_element.pressed.connect(lambda)
but the function _OnScienceDescription_pressed
can itself be passed as a callable without the need to define a lambda:
button_element.pressed.connect(_OnScienceDescriptor_pressed.bind(scienceid_element.text))
- Edited
Jesusemora because you are writing a function horizontally on an indentation language, it breaks the style and it's difficult to tell where the function begins and where it ends.
It's possible to make a lambda look almost like a normal function.
tween.tween_method(\
func(x: float):\
path_follow.progress_ratio =\
x if left_to_right else 1.0 - x;\
brush.position = path_follow.global_position,\
0.0, 1.0, duration)
But when it gets that complicated, it may be better not to use a lambda. I wrote that code not too long ago, and I can't remember what it's supposed to be doing.
- Edited
@Jesusemora @DaveTheCoder Dudes, lambdas don't need to be inlined or one-lined. They are like normal inner functions in Python. For example:
func add_repeated(src: Array, dest: Array) -> Array:
src = src.duplicate()
var f = func(a):
src.push_back(src.pop_front())
return a + src[-1]
return dest.map(f)
Even when inlined you can still write them "normally":
func add_repeated(src: Array, dest: Array) -> Array:
src = src.duplicate()
return dest.map(
func(a):
src.push_back(src.pop_front())
return a + src[-1]
)
One more benefit you get when using them as ad hoc callbacks is that they're not associated with any object. So if an object in whose method you created a lambda callable gets deleted, the callable (+its context/closure) will still be alive as long as there are existing references to it.
Jesusemora sorry for the late response. I have changed my code as per your suggestion. Thank you for the answer.