Tkinter Button Command Taking Only Newest Reference In Callback Parameter
"Thanks" * INFINITY
hum weirdly it worked ... not yet understood why!
Here is a post on it:
Thanks for all!
On Mon, Jul 8, 2019 at 5:40 PM Calvin Spealman <cspealma at redhat.com> wrote:
> This is a really common scoping issue to get tripped up on. I'll try to
> help you understand and work around it.
> for i, icon in enumerate(self.icons):
> print('// entering', icon.program)
> print('icons ... ... ... ...')
> pretty(icon.info, icon.program)
> x = Button(root, text=icon.info['name'] +'\n' + icon.info['version'],
> command=lambda: self.button_exec(icon))
> On the first line you enter a for loop where each iteration assigns a
> different pair of values to the names "i" and "icon".
> On the last line you create a lambda, an anonymous function, which you
> pass as the command callback for the button. Of course, no code inside the
> lambda is actually executed at this point. It is only after the entire for
> loop has completed, later when the user sees the buttons and clicks on one
> of them, that one of the lambda callbacks for the appropriate button will
> be executed.
> Now, when this happens, what is the value of "icon"? This involves a
> closure, which is how we describe the effect of the lambda (or any
> function) being created inside the scope of another function. The scope
> here which contains the "icon" variable is kept after the for loop and its
> container function is complete, because the lambda you create holds on to
> it in order to resolve variable names from. So all the lambda functions
> read the "icon" variable from this same scope, and at the time the loop
> completes that variable is assigned to the LAST value from the loop. That's
> why all the buttons get the same icon.
> There is a simple work around, however, called "rebinding". It is a trick
> you can do with default values for lambda or any function. Simply pass the
> icon as a default value for a parameter to the lambda, and the value at
> that time for one iteration of the loop will be bound to the callback you
> Just change this
> lambda: self.button_exec(icon)
> to this
> lambda icon=icon: self.button_exec(icon)
> I hope both the explanation and the example help!
> On Mon, Jul 8, 2019 at 1:59 AM Abdur-Rahmaan Janhangeer <
> arj.python at gmail.com> wrote:
>> I'm doing this project:
>> Everything works fine, except for one thing.
>> On line 60, the button is taking an object in it's command parameter
>> If you run the file, you'll see that all the different names are written
>> the gui just the callback is takest the newest icon object for all three
>> I know just a reference issue but it's been **bugging** me.
>> Thanks All
>> Abdur-Rahmaan Janhangeer
> CALVIN SPEALMAN
> SENIOR QUALITY ENGINEER
> cspealma at redhat.com M: +1.336.210.5107
> [image: https://red.ht/sig] <https://red.ht/sig>
> TRIED. TESTED. TRUSTED. <https://redhat.com/trusted>
http://www.pythonmembers.club | https://github.com/Abdur-rahmaanJ