简体   繁体   中英

Tkinter change button method based on button index or text

So I'm making a program that lets you create certain groups of apps and put them into presets. For example, a photography preset might have photoshop and spotify in it.

I'm having an issue with creating the buttons to open these apps. The way it works is that the name of the preset is put into a text file in a list with the apps that are in that preset. That list is then put into a list of lists, one list for each preset.

import tkinter as tk

root = tk.Tk()

presetList = ["Name1", "Program1", "Program2"], ["Name2", "Program3", 
"Program4"], ["Name3", "Program5", "Program6"]
nameList = ["Name1", "Name2", "Name3"]

def openPreset():
#I need this to open based on what button is pressed. So if you press the 
Name1 button, it calls the info from the list that Name1 is in.
  print(presetList)

x=7
y=10
for name in nameList:
  nameButton = tk.Button(root, text=name, width=20, height=1, 
  command=openPreset)
  nameButton.place(x=x,y=y)
  y+=25

root.mainloop()

The code above is what I'm using. What I'm wondering is, is there a way to make the method that's linked to the buttons in the last part of the code, can I make it do different things based on the text in the button? That way when I select Preset 1 for example, it will know just to open the apps in the same list that Preset 1 is part of? I've tried multiple different things and I feel like the way I'm trying to do it might just not work and that there's another way I should go about this.

Edit: I edited the code to be minimal so someone can help me with it. I need the function tied to each button to get each list based on the button pressed. These will be user entered presets in the future, so just simple if statements probably wouldn't work.

You can do it by creating a lambda function with a default argument value containing the information you want (and also modify the callback function to accept it.

Here's what I mean:

import tkinter as tk


root = tk.Tk()

presetList = (["Name1", "Program1", "Program2"],
              ["Name2", "Program3", "Program4"],
              ["Name3", "Program5", "Program6"])
nameList = ["Name1", "Name2", "Name3"]

def openPreset(name):
    print(name)

x=7
y=10
for name in nameList:
    nameButton = tk.Button(root, text=name, width=20, height=1,
                           command=lambda name=name: openPreset(name))
    nameButton.place(x=x, y=y)
    y+=25

root.mainloop()

Alternately you could just create a function the normal way inside the loop (which is an arguably more readable as well as an equally valid way of doing it).

for name in nameList:
    def callback(name=name):
        return openPreset(name)
    nameButton = tk.Button(root, text=name, width=20, height=1, command=callback)
    nameButton.place(x=x, y=y)
    y+=25

Like regular functions, lambda functions aren't required to have default arguments, or even any at all. However one is needed here to "capture" the current value of name variable since it changes as the for -loop executes, otherwise all the functions would receive the same argument value for it (which would be "Name3" since that's the final value it has when the loop's over).

I also suggest you read and start following the PEP 8 - Style Guide for Python Code so your code is more readable and follows the conventions.

Update

If you want to pass more info than just the preset name to the callback function, it would be fairly simple to pass the all the information to the callback function as shown below — note there's no longer a need for a separate nameList .

import tkinter as tk


root = tk.Tk()

presetList = (["Name1", "Program1", "Program2"],
              ["Name2", "Program3", "Program4"],
              ["Name3", "Program5", "Program6"])

def openPreset(group):
    name, app1, app2 = group  # Unpack list elements.
    print(name, app1, app2, sep=', ')

x=7
y=10
for app_group in presetList:
    def callback(group=app_group):
        return openPreset(group)

    nameButton = tk.Button(root, text=app_group[0], width=20, height=1, command=callback)
    nameButton.place(x=x, y=y)
    y+=25

root.mainloop()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM