i need to make this for 6 buttons...
If each button modifies the same global variable, then have make_something accept a value parameter:
from tkinter import Tk, Button
variable = 1
def make_something(value):
global variable
variable = value
root = Tk()
Button(root, text='Set value to four',command=lambda *args: make_something(4)).pack()
Button(root, text='Set value to eight',command=lambda *args: make_something(8)).pack()
Button(root, text='Set value to fifteen',command=lambda *args: make_something(15)).pack()
#...etc
If each button modifies a different global, then condense all your globals into a single global dict, which make_something can then modify.
from tkinter import Tk, Button
settings = {"foo": 1, "bar": 1, "baz": 1}
def make_something(name):
settings[name] = 2
root = Tk()
Button(root, text='Set foo',command=lambda *args: make_something("foo")).pack()
Button(root, text='Set bar',command=lambda *args: make_something("bar")).pack()
Button(root, text='Set baz',command=lambda *args: make_something("baz")).pack()
#...etc
In either case, you still only require one function.
If lambdas aren't to your taste, you could use nested functions to create separate callables for each command:
from tkinter import Tk, Button
settings = {"foo": 1, "bar": 1, "baz": 1}
def make_callback(key):
def make_something(*args):
settings[key] = 2
return make_something
root = Tk()
Button(root, text='Set foo',command=make_callback("foo")).pack()
Button(root, text='Set bar',command=make_callback("bar")).pack()
Button(root, text='Set baz',command=make_callback("baz")).pack()
#...etc
... And you can avoid globals by instead using attributes of a class instance:
from tkinter import Tk, Button
class GUI:
def __init__(self):
self.settings = {"foo": 1, "bar": 1, "baz": 1}
self.root = Tk()
Button(self.root, text='Set foo',command=self.make_callback("foo")).pack()
Button(self.root, text='Set bar',command=self.make_callback("bar")).pack()
Button(self.root, text='Set baz',command=self.make_callback("baz")).pack()
#...etc
def make_callback(self, key):
def make_something(*args):
self.settings[key] = 2
return make_something
gui = GUI()
By the way, don't do this:
myButton = Button(root).pack()
This assigns the result of pack() to myButton, so myButton will be None instead of referring to your button. Instead, do:
myButton = Button(root)
myButton.pack()
Answer from Kevin on Stack Overflowi need to make this for 6 buttons...
If each button modifies the same global variable, then have make_something accept a value parameter:
from tkinter import Tk, Button
variable = 1
def make_something(value):
global variable
variable = value
root = Tk()
Button(root, text='Set value to four',command=lambda *args: make_something(4)).pack()
Button(root, text='Set value to eight',command=lambda *args: make_something(8)).pack()
Button(root, text='Set value to fifteen',command=lambda *args: make_something(15)).pack()
#...etc
If each button modifies a different global, then condense all your globals into a single global dict, which make_something can then modify.
from tkinter import Tk, Button
settings = {"foo": 1, "bar": 1, "baz": 1}
def make_something(name):
settings[name] = 2
root = Tk()
Button(root, text='Set foo',command=lambda *args: make_something("foo")).pack()
Button(root, text='Set bar',command=lambda *args: make_something("bar")).pack()
Button(root, text='Set baz',command=lambda *args: make_something("baz")).pack()
#...etc
In either case, you still only require one function.
If lambdas aren't to your taste, you could use nested functions to create separate callables for each command:
from tkinter import Tk, Button
settings = {"foo": 1, "bar": 1, "baz": 1}
def make_callback(key):
def make_something(*args):
settings[key] = 2
return make_something
root = Tk()
Button(root, text='Set foo',command=make_callback("foo")).pack()
Button(root, text='Set bar',command=make_callback("bar")).pack()
Button(root, text='Set baz',command=make_callback("baz")).pack()
#...etc
... And you can avoid globals by instead using attributes of a class instance:
from tkinter import Tk, Button
class GUI:
def __init__(self):
self.settings = {"foo": 1, "bar": 1, "baz": 1}
self.root = Tk()
Button(self.root, text='Set foo',command=self.make_callback("foo")).pack()
Button(self.root, text='Set bar',command=self.make_callback("bar")).pack()
Button(self.root, text='Set baz',command=self.make_callback("baz")).pack()
#...etc
def make_callback(self, key):
def make_something(*args):
self.settings[key] = 2
return make_something
gui = GUI()
By the way, don't do this:
myButton = Button(root).pack()
This assigns the result of pack() to myButton, so myButton will be None instead of referring to your button. Instead, do:
myButton = Button(root)
myButton.pack()
Update : I have it working (almost) fine This code works but I'd like to display in real time And when I uncoment the 2 things it doesn't do anything anymore
def BotPlay_Button():
nPlay = entryN.get()
jlist = [Joueur(File1,True,File1),Joueur(File2,True,File1)]
Partie = Partie_Object(jlist)
for i in range(int(nPlay)):
Play_Partie(Partie)
xList.append(i)
y1List.append(bot1.score)
y2List.append(bot2.score)
# windo.update_idletasks()
# windo.update()
Videos
Is there a way to make a Tkinter Button change the value of a variable that I need somewhere else?
Here is my problem. I have a list of values, let us say "a[i]" with i=0...9.
I am listing the values, and then I want to ask the user for an entry to upgrade, and add 1 to that value. The user would enter the 'i', and then when clicking the button, the value of 'a[i]' would go up by 1. Here is my current code, that does not work. Any help would be greatly appreciated!
from tkinter import *
from tkinter import ttk
def upgradeByOne(iToUpgrade):
a[i] = a[i] + 1
# Define a list 'a' to start
a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
root = Tk()
mainwindow = ttk.Frame(root, width=200, height=200, padding="100 100 100 100")
mainwindow.grid(column=0, row=0, sticky=(N, W, E, S))
# Widgets for Main Window
ttk.Label(mainwindow, text="i").grid(column=0, row=0)
ttk.Label(mainwindow, text="a[i]").grid(column=1, row=0)
for i in range(0,10):
ttk.Label(mainwindow, text=i).grid(column=0, row=i+1)
ttk.Label(mainwindow, text=a[i]).grid(column=1, row=i+1)
ttk.Label(mainwindow, text="Which i would you like to upgrade?").grid(column=0, row=51, columnspan=3)
iToUpgrade = 0
whichIToUpgrade = ttk.Entry(mainwindow, width=7, textvariable=iToUpgrade)
whichIToUpgrade.grid(column=4, row=51, sticky=(W, E), columnspan=2)
ttk.Button(mainwindow, text="Upgrade",command= lambda: upgradeByOne(iToUpgrade)).grid(column=0,row=100,columnspan=5)
for child in mainwindow.winfo_children():
child.grid_configure(padx=5, pady=5)
# Main Loop
root.mainloop()
I'm close, but I think I'm missing something fundamental.
I'm programatically building some tkinter buttons and trying to get them to set a variable to some value (in this case, their own array index).
from tkinter import *
btnarray = [] array = []
def BtnClicked(obj, value):
obj = value
def CreateWindow():
for idx in range(10):
array.append(0)
btnarray.append(Button(root, text = f"Button {idx}", command = lambda a = idx: BtnClicked( array[a] , a)))
btnarray[-1].pack()
root = Tk()
CreateWindow()
while True:
root.update() structure is representative of the application I inherited and am trying to alter. Why isn't it writing the values to array? if I break inside 'BtnClicked', obj gets the value written, but that somehow doesn't pass back to array.
Thanks!
Whenever I try to use one button to set a value of a Global Variable, the second button attempting to utilize or show the different variable does not work. can anyone explain what is going on and how I'm supposed to have different variables altered by different commands? I've also tried using intVar and it does not work either. Still resets to 0
var = 0
def changevar ():
var = 1
print(var)
def printvar():
print(var)
window = tk.Tk()
button1 = tk.Button(master = window, text = "Set Var", command = changevar)
button1.pack()
button2 = tk.Button(master = window, text = "Display Var", command = printvar)
button2.pack()
window.mainloop()Solved it. Had to use the "set" command for intvar so:
var = tk.IntVar()
def changevar ():
var.set(1)
print(var.get())
def printvar():
print(var.get())Below code processes entry widget's text when Submit button is pressed.
import tkinter as tk
root = tk.Tk()
aVarOutside = 'asd'
def btn_cmd(obj):
#use global variable
global aVarOutside
#print its unmodified value
print("aVarOutside: " + aVarOutside)
#modify it with what's written in Entry widget
aVarOutside = obj.get()
#modify lblTextVar, which is essentially modifying Label's text as lblTextVar is its textvariable
lblTextVar.set(obj.get())
#print what's inside Entry
print("Entry: " + obj.get())
txt = tk.Entry(root)
txt.pack()
lblTextVar = tk.StringVar()
lbl = tk.Label(root, textvariable=lblTextVar)
lbl.pack()
btn = tk.Button(text="Submit", command=lambda obj = txt : btn_cmd(obj))
btn.pack()
root.mainloop()
When the button is pressed:
- Value of a global variable,
aVarOutsideis printed. - Value of
aVarOutsideis modified to the value of Entry box's (txt's) content. - Value of a textvariable used by a label (
lbl) is modified. Which means that the text oflblis updated and can be seen on the GUI. - Finally Entry box,
txt's content is printed.
I think you should use inputs() inside getInputs() and then button doesn't have to return any variables - and then you can use root.mainloop() instead of while loop.
import tkinter as tk
# --- functions ---
def inputs(text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input():
global action_input, extra_input, texts
text = textbox.get()
if text: # check if text is not empty
textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
action_input, extra_input, texts = inputs(text)
# --- main ---
root = tk.Tk()
textbox = tk.StringVar()
textbox_entry = tk.Entry(root, textvariable=textbox)
textbox_entry.pack()
submit = tk.Button(root, text="Submit", command=get_input)
submit.pack()
root.mainloop()
BTW: you could better organize code
- all functions before main part (
root = tk.Tk()) - PEP8 suggests to use
lower_case_namesfor functions and variables (instead ofCamelCaseNames)
global is not prefered method but I think it is better solution than yours.
If you don't need global then you can use classes with self.
import tkinter as tk
# --- classes ---
class Game:
def __init__(self):
self.root = tk.Tk()
self.textbox = tk.StringVar()
self.textbox_entry = tk.Entry(self.root, textvariable=self.textbox)
self.textbox_entry.pack()
self.submit = tk.Button(self.root, text="Submit", command=self.get_input)
self.submit.pack()
def run(self):
self.root.mainloop()
def inputs(self, text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input(self):
text = self.textbox.get()
if text: # check if text is not empty
self.textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
self.action_input, self.extra_input, self.texts = self.inputs(text)
# --- functions ---
# empty
# --- main ---
app = Game()
app.run()
This can be done using a lambda, like so:
button = Tk.Button(master=frame, text='press', command= lambda: action(someNumber))
This is a simple way to bind the argument without an explicit wrapper method or modifying the original action.
This can also be done by using partial from the standard library functools, like this:
from functools import partial
#(...)
action_with_arg = partial(action, arg)
button = Tk.Button(master=frame, text='press', command=action_with_arg)