0

I'm trying to populate a menu based on the data within a set. The only problem is that I want to be able to change a variable later on based on the menu item selected. What I currently have now doesn't work as expected. CurrentGenre is being printed out regardless of whether or not the item in the menu is being selected. Is there something I'm missing? Should I abandoned this line of thinking and try a different method? Should I perhaps be storing each of the self.genreMenu... I make somewhere so that I can refer to them later? Thanks

    for g in genres:
        self.genreMenu.add_command(label=g)
        self.genreMenu.bind("<Button-1>", self.change_genre(g))

        print(currentGenre)

def change_genre(self, label):
    global currentGenre

    currentGenre = label
    print (currentGenre)

I changed my code to use the command option in add_command instead. I've tried to use the lamba suggestion as mentioned below but I'm still unsure how to do it. I noticed that when not assigning currentGenre to label, currentGenre gets printed it but when assigned nothing gets printed out except for an initial list of the genres. Here's the code block in it's entirety. genres is a set.

    for i in data_load["genres"]:
        for j in i:
            genres.add(i["name"])

    for g in genres:
        genre_menus.append(self.genreMenu.add_command(label=g, command=self.change_genre(g)))

        #self.genreMenu.bind("<Button-1>", lambda event, g: self.change_genre(event, g))

def change_genre (self, label):
    global currentGenre
    currentGenre = label
    print (currentGenre).  
terratunaz
  • 614
  • 3
  • 9
  • 19
  • 1
    Why are you using `bind` with a menu? Are you aware of the `command` option? – Bryan Oakley Aug 14 '15 at 01:17
  • 1
    You are making a method-call with `self.genreMenu.bind("", self.change_genre(g))` change it to `self.genreMenu.bind("", lambda event, g: self.change_genre(event, g))` and add `event` to the methodheader – VRage Aug 14 '15 at 09:11
  • @ Bryan Oakley I originally used the command option but since it wasn't working I decided to use bind thinking that perhaps that was the issue. @ VRage I tried what you suggested. What do you mean by adding event to the methodheader? Passing it in as a parameter? I'm not very familiar with the concept of lamda. But I suspect thatI have to rename the method? – terratunaz Aug 18 '15 at 15:36
  • Also I may have forgotten to mention that not only am I trying to prevent the currentGenre from printing out while looping through the set but after the loop is done I want to be able to print out the contents of whichever value is stored in label based on what the has been selected. – terratunaz Aug 18 '15 at 18:25

1 Answers1

4

You have to give the menu a reference to a function. This can be done easily with lambda, which creates an anonymous function. You can have that function call your real function.

for g in genres:
    self.genreMenu.add_command(label=g, 
        command=lambda genre=g: self.change_genre(genre))

For a deeper explanation of lambda, see this answer: Why is Button parameter “command” executed when declared?

Community
  • 1
  • 1
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thank you so much Bryan! I'll read that answer for more info. Real quick though why is it that I must give the menu a reference to the function rather than the actual function? Why wouldn't it work when using the function directly? – terratunaz Aug 25 '15 at 18:16
  • "a reference to the function" _is_ "the actual function". You need to give it the function, not the _result_ of the function. When you do `command=self.change_genre(g)` you're actually calling `self.change_genre(g)`, and assigning the result to the command. This is all explained in the other answer I linked to. – Bryan Oakley Aug 25 '15 at 19:24