name 'coding' is not defined - python

I wanted to make a game like a clicker, where coding brings money, but I ran into this error. The error seems to be due to the fact that 'coding' is in another function, but I don't understand how I can fix it. Please help me. I will be very grateful to you
from tkinter import *
from time import sleep
from threading import *
from tkinter import ttk
from tkinter import messagebox
button_track = False
button_code = True
wait_code = 30
def check_code():
global button_code
if button_code == True:
money.set(money.get() + 50)
button_code = False
def buy_klava_func():
if money.get() >= 50:
money.set(money.get() - 50)
buy_klava.grid_remove()
coding = Button(root, text='Написать код', command=check_code)
coding.grid(column=0, row=0)
def timer_code():
global button_code
global wait_code
while True:
if button_code == False:
coding['state'] = 'disabled'
sleep(wait_code)
coding['state'] = 'active'
button_code = True
root = Tk()
root.geometry('900x900')
money = IntVar()
money.set(50)
buy_klava = Button(root, text='Купить клавиатуру (50 монет)', command=buy_klava_func)
buy_klava.grid(column=0, row=0)
th_timer_code = Thread(target=timer_code)
th_timer_code.start()
root.mainloop()

Looks like coding is not a global variable. Declare it above all the functions, so that you can use it within all functions.
from tkinter import *
from time import sleep
from threading import *
from tkinter import ttk
from tkinter import messagebox
button_track = False
button_code = True
wait_code = 30
def check_code():
global button_code
if button_code == True:
money.set(money.get() + 50)
button_code = False
def buy_klava_func():
global coding # <=== define coding as global
if money.get() >= 50:
money.set(money.get() - 50)
buy_klava.grid_remove()
coding = Button(root, text='Написать код', command=check_code)
coding.grid(column=0, row=0)
def timer_code():
global button_code
global wait_code
global coding
while True:
if button_code == False:
coding['state'] = 'disabled'
sleep(wait_code)
coding['state'] = 'active'
button_code = True
root = Tk()
root.geometry('900x900')
money = IntVar()
money.set(50)
buy_klava = Button(root, text='Купить клавиатуру (50 монет)', command=buy_klava_func)
buy_klava.grid(column=0, row=0)
th_timer_code = Thread(target=timer_code)
th_timer_code.start()
root.mainloop()

It is because coding is a local variable, so it cannot be accessed inside timer_code().
Since you just replace buy_klava by coding, my suggestion is simply to configure buy_klava instead of removing it and creating coding:
def buy_klava_func():
if money.get() >= 50:
money.set(money.get() - 50)
"""
buy_klava.grid_remove()
coding = Button(root, text='Написать код', command=check_code)
coding.grid(column=0, row=0)
"""
# just configure "buy_klava" instead of removing it and create "coding"
buy_klava.config(text='Написать код', command=check_code)
def timer_code():
global button_code
#global wait_code
while True:
if button_code == False:
buy_klava['state'] = 'disabled' # update buy_klava
sleep(wait_code)
buy_klava['state'] = 'active' # update buy_klava
button_code = True

Related

Why isnt my images showing in python tkinter?

so when I was trying o make a game the front page is good
Front page
but when I tried the game no image is shown. why? how can it get to fix it without changing the system order?
it always shows no image or just nothing in my other projects don't know why
a screen shot
here code:
from Tkinter import *
from PIL import Image,ImageTk
from Winsound import *
win = Tk()
win.config(bg="#e300ff")
win.geometry("950x600+160+60")
win.resizable(width = False, height = False)
def play_sound_play():
global playgame
PlaySound("SoundEffects\Coins.wav", SND_FILENAME)
playbtn.destroy()
win.config(bg="white")
playgame = True
game()
def printpos(event):
print(f"{plr_posx}")
def MoveLeft(event):
global plr_posx
if plr_posx == 311:
print("cant go into grass")
else:
plr_posx -= 150
plr.place(x=plr_posx,y=plr_posy)
def MoveRight(event):
global plr_posx
if plr_posx >= 610:
print("cant go into grass")
else:
plr_posx += 150
plr.place(x=plr_posx,y=plr_posy)
def game():
global plr
global plr_posx
global plr_posy
#road
road_img = ImageTk.PhotoImage(Image.open("texture\ymd.png"))
road = Label(win, image=road_img)
road.pack()
road.place(x=321,y=0)
#grass
grass_img = ImageTk.PhotoImage(Image.open("texture\grass.png"))
grass1 = Label(win, image=grass_img)
grass1.pack()
grass1.place(x=-2,y=0)
grass2 = Label(win, image=grass_img)
grass2.pack()
grass2.place(x=646,y=0)
#Plr pos
plr_posx=311
plr_posy=450
#Plr
plr_img = ImageTk.PhotoImage(Image.open("texture\Player.png"))
plr = Label(win, image=plr_img)
plr.pack()
plr.place(x=plr_posx,y=plr_posy)
if playgame == False:
print("2")
else:
print("1")
#controls
win.bind("<Left>",MoveLeft)
win.bind("<Right>",MoveRight)
win.bind("<p>",printpos)
def main():
global playbtn
#PlayBtn
play_btn = ImageTk.PhotoImage(Image.open("texture\play_btn.png"))
playbtn = Button(win, image=play_btn,bd=0,bg="#e300ff",activebackground='#e300ff', command=play_sound_play)
playbtn.pack()
playbtn.place(x=150,y=250)
win.mainloop()
main()
no error is shown
No Error
even after I close it
no error

How to stop this after function in python tkinter

I am trying to make a Stopwatch program and whenever i run it pressing the button , the function def watch() keeps executing itself and i cant stop it when needed.
is there any way to stop the execution of def watch() function after pressing the button?
Thanking you...
from tkinter import *
root = Tk()
tog = 0
hour = 0
mins = 0
sec = 0
def toggle():
global tog
tog = tog + 1
if tog == 1:
watch()
elif tog == 2:
stop()
tog = 0
def stop():
donothing = 0
def watch():
global sec
global hour
global mins
sec = sec + 1
l1.config(text=sec)
l1.after(1000,watch)
l1 = Label(root)
l1.pack()
Button(root,text="Start",command= lambda: toggle()).pack()
root.mainloop()
You should keep a reference to the after call, and cancel the callback when toggle is False. You can avoid ugly global declarations by using tkinter variables that are objects whose value can be read or set.
import tkinter as tk
def toggle_on_off():
toggle.set(not toggle.get())
if toggle.get():
watch()
def watch():
count_seconds.set(count_seconds.get() + 1)
if toggle.get():
_callback_id.set(root.after(1000, watch))
else:
root.after_cancel(_callback_id.get())
root = tk.Tk()
count_seconds = tk.IntVar(root)
count_seconds.set(0)
toggle = tk.BooleanVar(root)
toggle.set(False)
Button(root,text="Start",command=toggle_on_off).pack()
label = tk.Label(root, textvariable=count_seconds)
label.pack()
_callback_id = tk.StringVar(root)
_callback_id.set(None)
root.mainloop()
[Edit]
The same code with globals is like this:
import tkinter as tk
def toggle_on_off():
global toggle
toggle = not toggle
if toggle:
watch()
def watch():
global count_seconds, _callback_id
count_seconds += 1
label.configure(text=str(count_seconds))
if toggle:
_callback_id = root.after(1000, watch)
else:
root.after_cancel(_callback_id)
root = tk.Tk()
count_seconds = 0
toggle = False
Button(root,text="Start",command=toggle_on_off).pack()
label = tk.Label(root, text=str(count_seconds))
label.pack()
_callback_id = None
root.mainloop()
You can add a global variable , for eaxmple "exit",
and add an if statement before l1.after(1000,watch)
def toggle():
global tog, exit
exit = False
tog = tog + 1
if tog == 1:
watch()
elif tog == 2:
stop()
tog = 0
def watch():
global sec
global hour
global mins
global exit
sec = sec + 1
l1.config(text=sec)
if not exit:
l1.after(1000,watch)
in stop(), you can write
def stop():
global exit
exit = True

How to avoid using a global variable?

Getting back into programming after a 20 years hiatus. Been reading that the use of global variables in python is a sign of bad design, but can't figure out a better way of doing it.
Below is a small program that utilizes a global variable 'paused' to determine the state of the music player. This variable is utilized by a couple of functions.
Is there a better way of doing this without utilizing a global variable?
# Global variable to access from multiple functions
paused = False
def play_music():
global paused
if not paused:
try:
mixer.music.load(filename)
mixer.music.play()
statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
except:
tkinter.messagebox.showerror('File not found',
'Melody could not find the file.')
else:
mixer.music.unpause()
paused = False
statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
def stop_music():
mixer.music.stop()
statusBar['text'] = 'Music stopped'
def pause_music():
global paused
if not paused:
mixer.music.pause()
paused = True
statusBar['text'] = 'Music paused'
else:
play_music()
You could put all your functions inside a class, and make the "global" variable an attribute. In that way you can share it between methods:
class Player(object):
def __init__(self):
self.paused = False
def play_music(self):
if not self.paused:
# and so on
def pause_music(self):
if not self.paused:
# etc.
In case anyone else is interested, below is the improved code where a Player class was created to encapsulate the pause variable:
import os
from tkinter import *
from tkinter import filedialog
import tkinter.messagebox
from pygame import mixer
# Global variable to access from multiple functions
# paused = False
class Player:
def __init__(self):
self.paused = False
self.filename = None
def play_music(self):
if not self.paused:
try:
mixer.music.load(self.filename)
mixer.music.play()
statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
except FileNotFoundError:
tkinter.messagebox.showerror('File not found',
'Melody could not find the file. Please choose a music file to play')
else:
mixer.music.unpause()
self.paused = False
statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
#staticmethod
def stop_music():
mixer.music.stop()
statusBar['text'] = 'Music stopped'
def pause_music(self):
if not self.paused:
mixer.music.pause()
self.paused = True
statusBar['text'] = 'Music paused'
else:
self.play_music()
def rewind_music(self):
self.play_music()
statusBar['text'] = 'Music rewound'
#staticmethod
def set_volume(val):
# val is set automatically by the any tkinter widget
volume = int(val)/100 # mixer only takes value between 0 and 1
mixer.music.set_volume(volume)
# Create about us Message Box
#staticmethod
def about_us():
tkinter.messagebox.showinfo('About Melody', 'This is a music player built using python and tkinter')
def browse_file(self):
self.filename = filedialog.askopenfilename()
print(self.filename)
# Create main window
root = Tk()
# Create window frames
middle_frame = Frame(root)
bottom_frame = Frame(root)
# Create Menu
menu_bar = Menu(root)
root.config(menu=menu_bar)
# Create Player object
player = Player()
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Open", command=player.browse_file)
subMenu.add_command(label="Exit", command=root.destroy)
# it appears we can re-use subMenu variable and re-assign it
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Help", menu=subMenu)
subMenu.add_command(label="About Us", command=player.about_us)
# Initialise Mixer
mixer.init()
# Create and set the main window
root.title("Melody")
root.wm_iconbitmap(r'favicon.ico')
# root.geometry('300x300')
# Create and arrange widgets
text = Label(root, text="Lets make some noise!")
text.pack(pady=10)
middle_frame.pack(pady=30, padx=30) # Place the middle and bottom frame below this text
bottom_frame.pack()
playPhoto = PhotoImage(file='play-button.png')
playBtn = Button(middle_frame, image=playPhoto, command=player.play_music)
playBtn.grid(row=0, column=0, padx=10)
stopPhoto = PhotoImage(file='stop-button.png')
stopBtn = Button(middle_frame, image=stopPhoto, command=player.stop_music)
stopBtn.grid(row=0, column=1, padx=10)
pausePhoto = PhotoImage(file='pause-button.png')
pauseBtn = Button(middle_frame, image=pausePhoto, command=player.pause_music)
pauseBtn.grid(row=0, column=2, padx=10)
rewindPhoto = PhotoImage(file='rewind-button.png')
rewindBtn = Button(bottom_frame, image=rewindPhoto, command=player.rewind_music)
rewindBtn.grid(row=0, column=0, padx=20)
# Create and set volume slider
scale = Scale(bottom_frame, from_=0, to=100, orient=HORIZONTAL, command=player.set_volume)
scale.set(70) # set default slider and and volume
player.set_volume(70)
scale.grid(row=0, column=1, padx=10)
statusBar = Label(root, text='Welcome to Melody', relief=SUNKEN, anchor=W)
statusBar.pack(side=BOTTOM, fill=X)
# Keep main window displayed
root.mainloop()
Indeed, using global variable isn't recommended. You can have side effects that leads your program to have an unexpected behavior.
You have the possibility above (using class), but another solution is just to pass your variable as a parameter of your function.
def play_music(paused):
...
def stop_music(paused):
...
def pause_music(paused):
...
if you do not want to use classes, you could pass a settings dictionary that has a pause key, it will be mutated in all over your functions
def play_music(settings):
# some extra code
settings['pause'] = False
def stop_music(settings)
# some extra code
settings['pause'] = None
def pause_music(settings):
# some extra code
settings['pause'] = True
def main():
settings = {'pause': None}
play_music(settings)
.....

How to make timer/program open only after pressing key instead of immediately?

I need to make this clock open only after pressing a key, lets say "t". Now it opens immediately after running it.
import tkinter as tk
def update_timeText():
if (state):
global timer
timer[2] += 1
if (timer[2] >= 100):
timer[2] = 0
timer[1] += 1
if (timer[1] >= 60):
timer[0] += 1
timer[1] = 0
timeString = pattern.format(timer[0], timer[1], timer[2])
timeText.configure(text=timeString)
root.after(10, update_timeText)
def start():
global state
state=True
state = False
root = tk.Tk()
root.wm_title('Simple Kitchen Timer Example')
timer = [0, 0, 0]
pattern = '{0:02d}:{1:02d}:{2:02d}'
timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
timeText.pack()
startButton = tk.Button(root, text='Start', command=start)
startButton.pack()
update_timeText()
root.mainloop()
It is in another program so as I have my graphics window I will press "t" and the clock will open.
Keyboard is a python module that can detect keystrokes. Install it by doing this command.
pip install keyboard
Now you can do this.
while True:
try:
if keyboard.is_pressed('t'):
state = True
elif(state != True):
pass
except:
state = False
break #a key other than t the loop will break
I would recommend you to organize the code little bit, like class structure. One possible implementation would be like that:
import tkinter as tk
TIMER = [0, 0, 0]
PATTERN = '{0:02d}:{1:02d}:{2:02d}'
class Timer:
def __init__(self, master):
#I init some variables
self.master = master
self.state = False
self.startButton = tk.Button(root, text='Start', command=lambda: self.start())
self.startButton.pack()
self.timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
self.timeText.pack()
def start(self):
self.state = True
self.update_timeText()
def update_timeText(self):
if (self.state):
global TIMER
TIMER[2] += 1
if (TIMER[2] >= 100):
TIMER[2] = 0
TIMER[1] += 1
if (TIMER[1] >= 60):
TIMER[0] += 1
TIMER[1] = 0
timeString = PATTERN.format(TIMER[0], TIMER[1], TIMER[2])
self.timeText.configure(text=timeString)
self.master.after(10, self.update_timeText)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("900x600")
root.title("Simple Kitchen Timer Example")
graph_class_object = Timer(master=root)
root.mainloop()
So clock will start when you click to button. If you want to start the clock by pressing "t" in keyboard, you need to bind that key to your function.
You can also add functionality if you want to stop the clock when you click to the button one more time.
EDIT:
if you also want to start to display the clock by clicking the button, you can move the code for initializing the label in to start function.
def start(self):
self.state = True
self.timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
self.timeText.pack()
self.update_timeText()

How to set up multiple frames

This is a simple math game which is currently in progress. The loop starts off in mainGame() which then proceeds to mainMenu(). I am trying to create 2 frames; mframe and gframe in order to .destroy() the frames later on, essentially clearing the previous interface for the next one (similar to changing pages).
error:
Label(gframe, textvariable=self.question_var).pack() #gframe stands
for game frame NameError: name 'gframe' is not defined
from tkinter import *
from random import randint
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
class mainMenu:
def __init__(self):
gframe.destroy() #gets rid of previous interface
title = Label(mframe, text = "main menu").pack() #mfame stands for menu frame
class mainGame:
def __init__(self):
if start == False:
mframe.destroy() #gets rid of previous interface
#question
self.question_var = StringVar()
Label(gframe, textvariable=self.question_var).pack() #gframe stands for game frame
#answer
self.user_answer_var = StringVar()
entry = Entry(gframe, textvariable=self.user_answer_var)
entry.pack()
submit = Button(gframe, text = "submit", command = self.check_answer).pack()
#response output
self.response_var = StringVar()
self.count = 0
self.score = 0
Label(gframe, textvariable=self.response_var).pack()
#starts loop
self.ask_question()
root.mainloop()
def ask_question(self):
if self.count == 1:
self.endGame()
num1 = randint(1, 10)
num2 = randint(1, 10)
self.question_var.set("What is "+str(num1)+" + " +str(num2)+"?")
self.true_answer = num1 + num2
#print(self.true_answer) #testing purposes
def check_answer(self):
self.count += 1
user_answer = self.user_answer_var.get()
#print(user_answer) #testing purposes
if int(user_answer) == self.true_answer:
text = "Good job"
self.score += 1
else:
text = "Oh no"
self.response_var.set(text)
#clear answer for next loop
self.user_answer_var.set("")
self.ask_question()
def endGame(self):
print("endGame")
mainMenu()
mainGame()
As said in the comments above, the pack() method returns None. What you need to do is first create the two frames and assign them to variables, then pack them later. This way, the variables still point to the frame instances and not None.
You should change;
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
to;
root = Tk()
mframe = Frame(root)
gframe = Frame(root)
mframe.pack()
gframe.pack()
start = True

Categories

Resources