1

I have a function that creates buttons based on subfolders in a folder. It creates a button per subfolder, and gives it the name of the subfolder.

When pressed, I want the button to open another function and to pass that function its name.

def _sidepanel(self):
    curdir = "/Users/xxx/Desktop/Test/"
    layout = BoxLayout(orientation="vertical", pos_hint={"x": 0.0, "y": 0.0}, size_hint=(0.1,1))

    for folders in glob(join(curdir, "*")):
        name = basename(folders)
        btn = Button(text=name, on_press=lambda x: self._printname(name))
        layout.add_widget(btn)

    return layout

def _printname(self, name):
    print(name)

I have 5 subfolders, and I would expect a button to print its specific name, but instead they all print the name of the last folder run by the first function.

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
Bjarke
  • 25
  • 4
  • 1
    A more [mcve] snippet: [gist](https://gist.github.com/carcigenicate/ed2ed45fc180a0f694daf4e619cee510) – Carcigenicate Feb 01 '19 at 13:12
  • 1
    The value of name passed to self._printname(name) is not actually substituted until the button is pressed, meaning it will use whatever the most recent value of name is every time, in this case, the last folder in the directory. – InfiniteHigh Feb 01 '19 at 13:28
  • 1
    Possible duplicate of [What do (lambda) function closures capture?](https://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture) – Carcigenicate Feb 01 '19 at 13:36
  • That's the best explanation and description of a fix I could find. – Carcigenicate Feb 01 '19 at 13:36
  • 1
    [Here is a question related to adding buttons in a for loop using similar syntax as the question](https://stackoverflow.com/questions/32037769/how-do-i-link-python-tkinter-widgets-created-in-a-for-loop) – InfiniteHigh Feb 01 '19 at 13:39

1 Answers1

0

Your last link solved my question. Thanks - just attached my edited code.

def _sidepanel(self):
    curdir = "/Users/xxx/Desktop/Test/"
    layout = BoxLayout(orientation="vertical", pos_hint={"x": 0.0, "y": 0.0}, size_hint=(0.1,1))

    layout.add_widget(Button(text="Import\nPhotos"))
    layout.add_widget(Button(text="Create\nReport"))
    layout.add_widget(Button(text="Save?"))
    layout.add_widget(Button(text="Button 4"))

    for folders in glob(join(curdir, "*")):
        name = basename(folders)
        btn = Button(text=name, on_press=lambda n=name:self._showphotos(n))
        layout.add_widget(btn)

    return layout


def _showphotos(self, entry):
    print(entry.text)
Bjarke
  • 25
  • 4