-1

I am trying to create checkboxes from a list. (biomelis_ = ['Arctic','Hill','Coast', 'Desert', 'Forest','Grassland', 'Mountain', 'Swamp', 'Underdark','Underwater', 'Urban' ]).

I then want to check the boxes and press "go". I am trying to get the output to be a list. For example, if I check 'Arctic', 'Hill', and 'Coast', my output will be ['Arctic', 'Hill', 'Coast']. I have been reading through the documentation but I am struggling with this.

Here is the full code:

from tkinter import *

biomelis_ = ['Arctic', 'Hill', 'Coast', 'Desert', 'Forest', 'Grassland', 'Mountain', 'Swamp', 'Underdark', 'Underwater',
             'Urban']

root = Tk()
var = StringVar()


# var.set(biomelis_ [0])

def sel():
    biome_lis_selection = var.get()
    print(biome_lis_selection)
    return [biome_lis_selection]


for item in range(len(biomelis_)):
    l = Checkbutton(root, text=biomelis_[item], variable=var)
    print("l = Checkbutton(root, text=" + str(biomelis_[item]) + ", variable=" + str(var))
    l.pack(anchor='w')


def go():  ### runs tkinter

    biomes_Checklist = sel()
    b.config(state=NORMAL)
    b.delete('1.0', END)
    b.insert(INSERT, sel())
    b.config(state=DISABLED)


## defines go button. This launches the def go() when the go button is pressed.
go_button = Button(root, text="Go!", width=10, command=go)
go_button.pack()
b = Text(root)
b.pack()

root.mainloop()


This is the part that I am struggling with-getting the selected items.

l = Checkbutton(root, text=biomelis_[item], variable=var)

This returns 'l' instead of individual items in the list. Also all of the checkboxes check and uncheck at once.

B-L
  • 144
  • 1
  • 8
  • I thought that it would be defined in the line l = Checkbutton(root, text=biomelis_[item], variable=biomelis_[item]). so that variable=biomelis_[item] But I am guessing that is wrong – B-L Mar 22 '20 at 15:39
  • ***"I thought ... that variable=biomelis_[item]"***: That's a named argument, and is not how to assign a `variable=` to a `tkinter` widget. Read up on [The Variable Classes](http://effbot.org/tkinterbook/variable.htm) how to do it. – stovfl Mar 22 '20 at 15:43
  • Thank you. I have created a variable class called var = StringVar(). I then usevar.get(). I also changed the line l = Checkbutton(root, text=biomelis_[item], variable=var). I have edited the code above to reflect this. However, when I press go, the return is 'l'. Also all boxes check and uncheck at the same time (cannot check individual boxes). – B-L Mar 22 '20 at 15:58
  • ***"all boxes check and uncheck at the same time "***: You need a `variable=` per `Checkbutton(...`. Consider to use this approach: [correctly-extend-a-tkinter-widget-using-inheritance](https://stackoverflow.com/a/60322108/7414759) – stovfl Mar 22 '20 at 16:03

3 Answers3

1

You can assign an onvalue and offvalue to a checkbutton. If you set the onvalue to the value you want to retrieve and the off value to an empty string, fetching the values becomes very simple.

The first thing we want to do is throw away the block of code that is using exec. It's simply not necessary. We'll create the variables at the same time we create the checkbuttons, and append them to a list.

Second, we'll loop directly over biomelis_, and define the onvalue to be the same as the text:

vars = []
for biome in biomelis_:
    var = tk.StringVar(value="")
    vars.append(var)
    cb = tk.Checkbutton(root, text=biome, onvalue=biome, offvalue="", variable=var)
    cb.pack(side="top", anchor="w")

With that, getting the values is just a matter of iterating over the list of variables and keeping the values that aren't the empty string:

def sel()
    selected = []
    for var in vars:
        value = var.get()
        if value != "":
            selected.append(value)
    return selected

That loop be reduced to the following one-liner, though it's harder to read if you're just starting out with python:

def sel():
    return [var.get() for var in vars if var.get()]
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I have one more quick question for you. vars is showing up as a global variable, which is great in this instance. At what point in the code is it declared as a global variable? – B-L Mar 22 '20 at 21:19
  • @Brack It's not declared global, it's global by the fact that it is created in the global scope. If you run this code inside another function, that's when you would have to declare it as global. – Bryan Oakley Mar 22 '20 at 21:21
1

In my solution I assign as separate BooleanVarto each Checkbutton to hold each widget's current state (i.e. "checked" or "unchecked") separately, and also save each of the Checkbuttons in a list named chkbtns. This makes it easy to refer to them in the other functions.

from tkinter import *

root = Tk()

biomelist = ['Arctic', 'Hill', 'Coast', 'Desert', 'Forest', 'Grassland', 'Mountain',
             'Swamp', 'Underdark', 'Underwater', 'Urban']

chkbtns = []
for biome in biomelist:
    btnvar = BooleanVar(value=False)
    chkbtn = Checkbutton(root, text=biome, variable=btnvar)
    chkbtn.var = btnvar  # Save associated tkinter variable.
    chkbtn.pack(anchor='w')
    chkbtns.append(chkbtn)

def sel():
    selected = [btn.cget('text') for btn in chkbtns if btn.var.get()]
    print(f'selected: {selected}')
    return selected

def go():
    biomes_Checklist = sel()
    b.config(state=NORMAL)
    b.delete('1.0', END)
    b.insert(INSERT, biomes_Checklist)
    b.config(state=DISABLED)

# Defines Go button. This launches the go() function when the go button is pressed.
go_button = Button(root, text="Go!", width=10, command=go)
go_button.pack()
b = Text(root)
b.pack()

root.mainloop()
martineau
  • 119,623
  • 25
  • 170
  • 301
  • You don't need to do a `for in range...`. You can directly iterate over the list `for _ in biomelis_` – Bryan Oakley Mar 22 '20 at 18:00
  • @Bryan: I know, I did it that way for consistency with the `for` loop that creates the `Checkbutton`s (and it didn't seem worth "optimizing"). – martineau Mar 22 '20 at 18:03
0

This can solve your problem,but I think there is more safe and good way to do this:

BTW,maybe you don't know how to use variable.read some documents

from tkinter import *

biomelis_ = ['Arctic', 'Hill', 'Coast', 'Desert', 'Forest', 'Grassland', 'Mountain', 'Swamp', 'Underdark', 'Underwater',
             'Urban']

biomelis_variable = [] # a list to save all the variable

root = Tk()

for i in biomelis_:
    exec('''
{0} = IntVar()
biomelis_variable.append({0}) # use exec()
'''.format(i))

def sel():
    biome_lis_selection = []
    for i in range(len(biomelis_)):
        check = biomelis_variable[i].get()
        if check:
            biome_lis_selection.append(biomelis_[i])

        # biome_lis_selection = var
    return biome_lis_selection # the selected checkbutton name


for item in range(len(biomelis_)):
    l = Checkbutton(root, text=biomelis_[item], variable=biomelis_variable[item])
    l.pack(anchor='w')


def go():  ### runs tkinter

    biomes_Checklist = sel()
    b.config(state=NORMAL)
    b.delete('1.0', END)
    b.insert(INSERT, sel())
    b.config(state=DISABLED)


## defines go button. This launches the def go() when the go button is pressed.
go_button = Button(root, text="Go!", width=10, command=go)
go_button.pack()
b = Text(root)
b.pack()

root.mainloop()


jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49