Hey guys,

I've been fiddling around with Tkinter for a bit and can't for the love of me figure out why this code won't work. I'm making a GUI that outputs the price of a product depending on what buttons the user pressed. I have three calculations that revolve around the buttons pressed and no matter what button I press, the same value is outputted.

I start the code by defining the two values I want the user to be able to dictate.

d = 0
n = 0

Now I make a button and I want it so that when the user clicks this button, the value of d is changed.

def d1():
    d = 10
d1 = Button(text="Click Me", command=d1).pack()

Likewise, the same applies for the other variable.

def n1():
    n = 1
n1 = Radiobutton(root, text="Click me!", variable=n1).pack()

Theoretically, when I click these buttons or d2, n2, d3, n3... the stock value of d and n which have been posted at the top should change allowing the calculation to process a different result and the value output to be different.

Hope you can help, thanks.

user45949219
Deleted Member

In the first example, both the function and the button object are assigned to the same variable name, so "d1" can refer to either one (you may or may not be calling the function). Second. the function could set a Tkinker StringVar, used as a textvariable of the button, to the value (but there are other ways also). The second button, n1, does not call a function when called. I'm sorry, but your code is not complete enough to fix. I would suggest a Google for "Tkinter button Daniweb".

Edited 5 Years Ago by woooee: n/a

It's always difficult to set the value of global variables in functions. It can be done with the global statement, but it is usually simpler when the values are attributes of an existing object instead of global variables. If there is no such object, you can create one artificially

glob = type('Globvars', (object,), {})() # object to hold global variables

glob.d = 0
glob.n = 0

def d1():
    glob.d =  10 # this works

if __name__ == "__main__":
    d1()
    print vars(glob)

""" my output --->
{'d': 10, 'n': 0}
"""

Edited 5 Years Ago by Gribouillis: n/a

It's always difficult to set the value of global variables in functions. It can be done with the global statement, but it is usually simpler when the values are attributes of an existing object instead of global variables. If there is no such object, you can create one artificially

glob = type('Globvars', (object,), {})() # object to hold global variables

glob.d = 0
glob.n = 0

def d1():
    glob.d =  10 # this works

if __name__ == "__main__":
    d1()
    print vars(glob)

""" my output --->
{'d': 10, 'n': 0}
"""

That is all well and good but how do I interpret this into a GUI where I have say 4 options and I want them to select one therefore changing the the result produced. I tested out that piece of code there and it only seems to work with 1 variable unless I'm mistaken.

Cheers.

That is all well and good but how do I interpret this into a GUI where I have say 4 options and I want them to select one therefore changing the the result produced. I tested out that piece of code there and it only seems to work with 1 variable unless I'm mistaken.

Cheers.

You can use functools.partial() like this

from functools import partial
from Tkinter import *
glob = type('Globvars', (object,), {})()
glob.d = 0
master = Tk()

def on_press(value):
    glob.d = value
    print glob.d

buttons = list()
for value in (10, 20, 30):
    b = Button(master, text = str(value), command = partial(on_press, value))
    b.pack(side=LEFT)
    buttons.append(b)

mainloop()

Edited 5 Years Ago by Gribouillis: n/a

Comments
Helpful.

Many thanks for your help Grib!

Of course we have object say our master, and as Buttons are in global scope they need not be saved as they will not be garbage collected.

from functools import partial
from Tkinter import *
master = Tk()

def on_press(value):
    master.d = value
    master.title(str(master.d))

for value in (10, 20, 30):
    Button(master, text = str(value),
           command = partial(on_press, value)).pack(side=LEFT)

mainloop()

Of course we have object say our master, and as Buttons are in global scope they need not be saved as they will not be garbage collected.

from functools import partial
from Tkinter import *
master = Tk()

def on_press(value):
    master.d = value
    master.title(str(master.d))

for value in (10, 20, 30):
    Button(master, text = str(value),
           command = partial(on_press, value)).pack(side=LEFT)

mainloop()

Thanks for your reply also! Question though, say I wanted to change the name of the button displayed to the user from 10, 20, 30 to A, B, C or xyz what would I have to do?

I tried to do this, to no avail.

name = ("Name")
name1 = ("Name 1")
name2 = ("Name 2")

for value in (10, 20, 30):
    Button(root, text = (name, name1, name2),
           command = partial(on_press, value)).pack(side=LEFT)
for value in ('Name 1', 'Name 2' , 'Name 3'):
    Button(root, text = value,
           command = partial(on_press, value)).pack(side=LEFT)

Something like that, is that what you're after?

What you were trying to do was create a button with the text set to the tuple (name, name1, name2) for each value in the tuple (10,20,30).

Edited 5 Years Ago by Enalicho: n/a

for value in ('Name 1', 'Name 2' , 'Name 3'):
    Button(root, text = value,
           command = partial(on_press, value)).pack(side=LEFT)

Something like that, is that what you're after?

What you were trying to do was create a button with the text set to the tuple (name, name1, name2) for each value in the tuple (10,20,30).

I'd like to retain the values '10', '20', '30' yet have the labels 'Name 1', 'Name 2', 'Name 3' for each respective one. How would I go about doing that?

I'd like to retain the values '10', '20', '30' yet have the labels 'Name 1', 'Name 2', 'Name 3' for each respective one. How would I go about doing that?

for name, value in zip(('Name 1', 'Name 2' , 'Name 3'), (10, 20, 30)):
    Button(root, text = name,
           command = partial(on_press, value)).pack(side=LEFT)
This article has been dead for over six months. Start a new discussion instead.