Take a look at the example code below. There is a main window, which calls the function fun2 to display the value of variable a (as a label w/ text). At the same time, a menu item on the main window launches a secondary window (function fun1) with two buttons. I am trying to find a way to change the value of a through these buttons.
If I do not include the global variable a = 0 (line 6), I get a "global name 'a' is not defined" error. If I do include it (as in this example), the window buttons don't have any effect on the variable (it remains a = 0). I've tried using the command global a in fun1, with no effect. I've also experimented using the same command also in fun2 but I still can't get it to work.
Any ideas? What am I doing wrong?
import Tkinter
import random
import time
from Tkinter import *
a = 0
def fun1():
win2 = Toplevel()
win2.geometry("300x300")
def var_yes():
a = 1
win2.after(500, lambda: win2.destroy())
def var_no():
a = 0
win2.after(500, lambda: win2.destroy())
button1 = Tkinter.Button(win2, text ="1", command = var_yes).pack()
button2 = Tkinter.Button(win2, text ="2", command = var_no).pack()
def fun2():
value = 0
if a == 1:
value = a
granresult = "{}".format(value)
lbl.configure(text = str(granresult))
def gui_stuff(window):
global lbl
window.configure(background="#000000")
window.geometry("700x500")
lbl = Tkinter.Label(window, height=5, anchor = "c", text="Label", bg="#000000", fg="#ffffff", font=("Helvetica", 22))
lbl.pack()
fun2()
window = Tkinter.Tk()
menubar = Menu(window)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Program", menu=filemenu)
filemenu.add_command(label="test", command=fun1)
window.config(menu=menubar)
gui_stuff(window)
window.update()
winx1 = window.winfo_rootx()
winy1 = window.winfo_rooty()
winh1 = window.winfo_height()
window.mainloop()
The global statement must be used in the function that assigns to the variable. It does not carry over into sub-functions, which is why it didn't have an effect in fun1. You have to add it to both var_yes and var_no.
What you are doing wrong is thinking that global variables are a good idea. Then not understanding how to use them. In python you create a global by assignment in the module level scope. You have done that by creating a value and calling it a
In each function which needs to write `a' you need to declare as global. See the code
import Tkinter
import random
import time
from Tkinter import *
a = 0
def fun1():
win2 = Toplevel()
win2.geometry("300x300")
def var_yes():
global a
a = 1
win2.after(500, lambda: win2.destroy())
def var_no()
global a
a = 0
win2.after(500, lambda: win2.destroy())
button1 = Tkinter.Button(win2, text ="1", command = var_yes).pack()
button2 = Tkinter.Button(win2, text ="2", command = var_no).pack()
def fun2():
global a
value = 0
if a == 1:
value = a
granresult = "{}".format(value)
lbl.configure(text = str(granresult))
def gui_stuff(window):
# the next line refers to a global which doesn't exist
global lbl
window.configure(background="#000000")
window.geometry("700x500")
lbl = Tkinter.Label(window, height=5, anchor = "c", text="Label", bg="#000000", fg="#ffffff", font=("Helvetica", 22))
lbl.pack()
fun2()
window = Tkinter.Tk()
menubar = Menu(window)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Program", menu=filemenu)
filemenu.add_command(label="test", command=fun1)
window.config(menu=menubar)
gui_stuff(window)
window.update()
winx1 = window.winfo_rootx()
winy1 = window.winfo_rooty()
winh1 = window.winfo_height()
window.mainloop()
Related
My code:
def Click():
global output
output = StringVar()
output = random.randint(1, 6)
global outputL
outputL = Label(root, text = f"The number is... {output}")
outputL.pack()
output = 0
How do I make it hide the label after that?
Use after method and config method
(TIP) Don't create a widgets(Labels, Buttons, etc...) inside a function. Use config method to update your widgets
from tkinter import *
import random
root = Tk()
def Remove_Output():
outputL.pack_forget()
def click():
global output
output = StringVar()
output = random.randint(1, 6)
outputL.config(text=f"The number is... {output}")
outputL.pack()
output = 0
root.after(1000, Remove_Output)
btn = Button(root, text="Click",command=click)
btn.pack()
outputL = Label(root, text = "")
root.mainloop()
I'm making a GUI where I can turn on a loop, but when I start my loop it's not automatically running. In this case it's not automatically printing "Test". I first have to click on the Check Variable option
I tried moving the code up and down but it doesn't work
# import tkinter
from tkinter import *
# 1 = on
# 3 = off
# Define Default variable
global x
x = 3
# Window preferences
root = Tk()
# Change Variables
def changeVar1():
global x
x = 1
def changeVar2():
global x
x = 3
def printVariable():
print(x)
# loop
while x < 2:
print ("Test")
# Buttons
button_1 = Button(root, text="Start", command=changeVar1)
button_2 = Button(root, text="End", command=changeVar2)
button_3 = Button(root, text="Check variable", command=printVariable)
# Button Posistion
button_1.pack()
button_2.pack()
button_3.pack()
root.mainloop()
You need to use after method, and don't create while loop inside tkinker main loop, because main loop will handle this.
=^..^=
from tkinter import *
x = 6
root = Tk()
def changeVar1():
global x
x = 1
def changeVar2():
global x
x = 3
def printVariable():
print(x)
# Buttons
button_1 = Button(root, text="Start", command=changeVar1)
button_2 = Button(root, text="End", command=changeVar2)
button_3 = Button(root, text="Check variable", command=printVariable)
# Button Posistion
button_1.pack()
button_2.pack()
button_3.pack()
# set timer delay for after method
time_delay = 100 # should by > 0
def task_function():
if x < 2:
print("test")
# repeat after method
root.after(time_delay, task_function)
# set after method
root.after(time_delay, task_function)
root.mainloop()
so i'm trying to create a code which when each button is clicked it will make that button fit a certain style but with changes to the name, however my current code will replace the button you click and them when you click on another it disables the last one you clicked permanently is there anyway to make it so that the buttons all use the same function but dont get disabled when you activate another button?
from tkinter import *
MainWindow = Tk()
def SquadInfoBttnFull():
global SquadFullBttn
SquadFullBttn = Toplevel(MainWindow)
SquadFullBttn.geometry("658x600")
# -- unit buttons -- #
for i in range(10):
Unit_Button = Button(SquadFullBttn, text="EMPTY", width=8, height=6)
Unit_Button.grid(row = 0, column = i)
Unit_Button.bind("<Button-1>", UnitFill)
def SquadInfoBttn():
InfoBttn = Button(MainWindow, wraplength=50, justify=LEFT, text="SquadInfo Here", width=100, command=SquadInfoBttnFull)
InfoBttn.grid(row=0, column=0, sticky=W)
def UnitInfoBttn():
UnitInfo = Toplevel(SquadFullBttn)
UnitInfo.geometry("300x200")
def UnitFill(event):
global photo
photo = PhotoImage(file="csmSingle.png")
btn = event.widget
grid_info = event.widget.grid_info()
btn = Button(SquadFullBttn, text="UNIT", image=photo, width=58, height=93, command=UnitInfoBttn, compound = TOP)
btn.grid(row=grid_info["row"], column=grid_info["column"], sticky=E)
SquadInfoBttn()
MainWindow.mainloop()
You are trying to make changes to the existing button and not create a new one. Also, you don't need to create a new instance of PhotoImage every time. The following code works for me:
from tkinter import *
MainWindow = Tk()
photo = PhotoImage(file="csmSingle.png")
def SquadInfoBttnFull():
global SquadFullBttn
SquadFullBttn = Toplevel(MainWindow)
SquadFullBttn.geometry("658x600")
# -- unit buttons -- #
for i in range(10):
Unit_Button = Button(SquadFullBttn, text="EMPTY", width=8, height=6)
Unit_Button.grid(row = 0, column = i)
Unit_Button.bind("<Button-1>", UnitFill)
def SquadInfoBttn():
InfoBttn = Button(MainWindow, wraplength=50, justify=LEFT, text="SquadInfo Here", width=100, command=SquadInfoBttnFull)
InfoBttn.grid(row=0, column=0, sticky=W)
def UnitInfoBttn():
UnitInfo = Toplevel(SquadFullBttn)
UnitInfo.geometry("300x200")
def UnitFill(event):
btn = event.widget
grid_info = event.widget.grid_info()
btn.config(text="UNIT", image=photo, width=58, height=93, command=UnitInfoBttn, compound = TOP)
btn.grid(row=grid_info["row"], column=grid_info["column"], sticky=E)
SquadInfoBttn()
MainWindow.mainloop()
I am making a pop up window ,on press of a button on main window. The pop up window have many check buttons, I need to get the state of the check buttons back to main window and also to make use of a select all and deselect all button. But I am getting error using the variables, and not able to pass the states back to main window.
Here is the program I wrote:
import Tkinter
import tkMessageBox
top = Tkinter.Tk()
state=[[]]
def popup(x):
def select_clear_states():
global Vars, all_states
states = all_states.get()
if states == 0:
for I in range(len(Vars)):
Vars[I].set(0)
if states == 1:
for I in range(len(Vars)):
Vars[I].set(1)
Vars = []
root = Tkinter.Tk()
all_states = Tkinter.IntVar()
select_all = Tkinter.Checkbutton(root, text = "select/deselect all",variable = all_states, command = select_clear_states)
select_all.grid(row = 0, column = 0, padx = 5, pady = 1)
for n in range(10):
var = Tkinter.IntVar()
Vars.append(var)
checkbox = Tkinter.Checkbutton(root, text = n+1, variable= Vars[n])
checkbox.grid(row = n+1, column = 0, padx = 5, pady = 1)
root.mainloop()
A = Tkinter.Button(top, text ="Hello1",command=lambda: popup(1))
A.pack()
B = Tkinter.Button(top, text ="Hello2",command=lambda: popup(2))
B.pack()
C = Tkinter.Button(top, text ="Hello3",command=lambda: popup(3))
C.pack()
top.mainloop()
am not able to make use of the variables Vars all_state and state[[]], to get he state of the check button.am getting this error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
return self.func(*args)
File "C:\Users\Synapse\Documents\Neo\Tutorial\python_tutorial\button.py", line 11, in select_clear_states
states = all_states.get()
NameError: global name 'all_states' is not defined
I should be able to use select/deselectall button and also able to get back all states of each check button to main window.
Example code using class.
It use Toplevel() to create PopUp because Tkinter should have only one Tk() window.
And it use only one mainloop() because more loops make problem with values in variables.
It can created different number of checkboxes.
It needs more work - ie. to return values - but now you can use win.states to get states of all checkboxes (or to set them).
import Tkinter as tk
import tkMessageBox
# --- classes --- (CamelCase names)
class PopUp(tk.Toplevel):
def __init__(self, number=10):
tk.Toplevel.__init__(self)
# - global checkbox to set all "small" checkboxes -
self.global_state = tk.BooleanVar()
cb = tk.Checkbutton(self, text="select/deselect all",
variable=self.global_state,
command=self.select_clear_states)
cb.grid(row=0, column=0, padx=5, pady=1)
# - "small" checkboxes -
self.states = []
for n in range(1, number+1):
var = tk.BooleanVar()
cb = tk.Checkbutton(self, text=str(n), variable=var)
cb.grid(row=n, column=0, padx=5, pady=1)
self.states.append(var)
def select_clear_states(self):
# get global checkbox
state = self.global_state.get()
# set all "small" checkboxes
for x in self.states:
x.set(state)
# --- functions --- (lower_case names)
def popup(num):
win = PopUp(num)
#win.states[1].set(True)
# --- main --- (lower_case names)
root = tk.Tk()
b = tk.Button(root, text="5 checkboxes", command=lambda:popup(5))
b.pack()
b = tk.Button(root, text="10 checkboxes", command=lambda:popup(10))
b.pack()
b = tk.Button(root, text="3 checkboxes", command=lambda:popup(3))
b.pack()
root.mainloop()
I'm trying to use messagebox.showinfo to show a message when my counter reach 4.
import tkinter
from tkinter import *
global cptBalle
global cptPrise
cptBalle = 0
cptPrise = 0
cptRetrait = 0
cptManche = 1
ptsVisiteur = 0
ptsReceveur = 0
coupSurVisiteur = 0
coupSurReceveur = 0
erreurVisiteur = 0
erreurReceveur = 0
equipeAuBaton = "visiteur"
def balle():
global cptBalle
global cptPrise
cptBalle += 1
if cptBalle == 4:
messagebox.showinfo(title="Balle", message="Testtest")
cptBalle = 0
cptPrise = 0
def prise():
pass
def fausse_balle():
pass
def retrait():
pass
def balle_passee():
pass
def mauvais_lancer():
pass
def sacrifice():
pass
def simple():
pass
def double():
pass
def triple():
pass
def circuit():
pass
def atteint():
pass
def erreur():
pass
def creer_bouton():
btnBalle = Button(app, text="Balle", command=balle)
btnBalle.grid(row=1, column=0)
btnPrise = Button(app, text="Prise", command=prise)
btnPrise.grid(row=2, column=0)
btnFausse_balle = Button(app, text="Fausse balle", command=fausse_balle)
btnFausse_balle.grid(row=3, column=0)
btnRetrait = Button(app, text="Retrait", command=retrait)
btnRetrait.grid(row=4, column=0)
btnBalle_passee = Button(app, text="Balle passee", command=balle_passee)
btnBalle_passee.grid(row=5, column=0)
btnMauvais_lancer = Button(app, text="Mauvais lancer", command=mauvais_lancer)
btnMauvais_lancer.grid(row=6, column=0)
btnSacrifice = Button(app, text="Sacrifice", command=sacrifice)
btnSacrifice.grid(row=7, column=0)
btnSimple = Button(app, text="Simple", command=simple)
btnSimple.grid(row=8, column=0)
btnDouble = Button(app, text="Double", command=double)
btnDouble.grid(row=9, column=0)
btnTriple = Button(app, text="Triple", command=triple)
btnTriple.grid(row=10, column=0)
btnCircuit = Button(app, text="Circuit", command=circuit)
btnCircuit.grid(row=11, column=0)
btnAtteint = Button(app, text="Atteint", command=atteint)
btnAtteint.grid(row=12, column=0)
btnErreur = Button(app, text="Erreur", command=erreur)
btnErreur.grid(row=13, column=0)
root = tkinter.Tk()
root.title("Baseball!")
root.geometry("750x350")
app = Frame(root)
app.grid()
creer_bouton()
root.mainloop()
The first button "btnBalle" call the function "Balle()".
It works when I run it in Python IDLE but when I use PyCharm, it doesn't.
Obviously that's not your whole program, but… let's assume your real program is calling Test() multiple times, but isn't actually starting the Tk runloop anywhere, or even creating a top-level Tk object. So, any Tkinter windows you try to display will never show up. (Actually, on some platforms, like OS X, it will show up—but it shouldn't, and if it doesn't on your platform, that's not a bug.)
Why does it work in IDLE? Because IDLE itself is written in Tkinter, and the tricks it uses to allow you to use the interactive interpreter while you've got a GUI program running also allow you to get away with this. That's not something you should rely on.
I ran into the same problem when attempting to use the messagebox class.
The basis of the code was:
import tkinter as tk
tk.messagebox.showinfo( --- )
I resolved the issue by adding:
from tkinter import messagebox
and then calling:
messagebox.showinfo( --- )
Hope this helps.