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()
Related
**I am writing a baseball counting program. I have a label for walks and strikeouts. To the side of those labels I have buttons with the text "+1". I want the buttons to be able to change and print the number of walks and strikeouts every time I click the +1 buttons. I just need some ideas to help get started. Here is my code for clarification: **
import tkinter as tk
from tkinter.constants import COMMAND, X
global walk_counter
walk_counter = 0
global strikeout_counter
strikeout_counter = 0
def main(): # This is the main function
root = tk.Tk()
frame = tk.Frame(root)
frame.master.title("Random Title")
frame.pack(padx=4, pady=3, fill=tk.BOTH, expand=1)
populate_boxes(frame)
root.mainloop()
def populate_boxes(frame):
walks_label = tk.Label(frame, text="BB:")
walks_entry = tk.Label(frame, width=4)
walks_button = tk.Button(frame,text="+1")
strikeouts_label = tk.Label(frame,text="Strikeouts:")
strikeouts_entry = tk.Label(frame,width=4)
strikeouts_button = tk.Button(frame,text="+1")
walks_label.place(x=200,y=500)
walks_entry.place(x=250,y=500)
walks_button.place(x=300,y=500)
strikeouts_label.place(x=400,y=500)
strikeouts_entry.place(x=450,y=500)
strikeouts_button.place(x=500,y=500)
def add_more_walks():
global walk_counter
walk_counter += 1
walks_entry.config(text = walk_counter)
add_more_walks()
main()
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()
Im making this game called:
IDLE PEN ,(MAKE PENS)
and every 1 second i get a bonus pen
how i get a bonus pen is doing this
Import time
While true
make a pen()
time.sleep(1)
but i have some code under the while true loop.
the code under the while true loop is like buttons to
upgrade the pens or make a pen
So how do i make the code under the while true loop work?
This is my game im happy for anyone to copy it
its not ready yet
import functools
import tkinter
import tkinter.messagebox
import time
from random import seed
from random import randint
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
window = tkinter.Tk()
window.title('Idle Pen')
def print_pen(number: int):
return f"Pens: {number}"
class pencount:
def __init__(self):
self.pencount = 0
self.text = tkinter.Text(height=1, width=30)
self.text.insert("1.0", print_pen(0))
self.text['state'] = 'disabled'
self.text.pack()
def changepencount(self, count):
if self.pencount + count < 0:
return
self.pencount = self.pencount + count
self.text['state'] = 'normal'
self.text.delete("1.0", "end")
self.text.insert("1.0", print_pen(self.pencount))
self.text['state'] = 'disabled'
self.text.pack()
pen = pencount()
changepenup = functools.partial(pen.changepencount, 1)
B = tkinter.Button(window, text="Make Pen", command=changepenup)
changependown = functools.partial(pen.changepencount, -100)
A = tkinter.Button(window, text='Penmaker', command=changependown)
Q = tkinter.Button(window, text="Quit", command=window.destroy)
U = tkinter.Button
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
B.pack()
A.pack()
Q.pack()
window.mainloop()
You could use threading to run your loop in separated thread and then main thread may run tkitner
OR you can use tkinter function after() (instead of while True) to run function with delay and this function should use again after() to run itself.
import tkinter as tk
# --- functions ---
def update():
global value
value += 1
text = f'make penny: {value}'
print(text)
label['text'] = text
# run again after 1s (1000ms)
root.after(1000, update)
# --- main ---
value = 0
root = tk.Tk()
label = tk.Label(root, text="make penny: 0")
label.pack()
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
# run first time after 1s (1000ms)
root.after(1000, update)
root.mainloop()
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()
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.