“name is not defined” inside function - python

I want to create a countdown clock and I almost did but if I run this code down below and press the 'go' button, I get the error: NameError: name 'be' is not defined. Even if I try to put global be in there it doesn't seem to work
import tkinter as tk
def set1():
global be
if be1 is not '':
be = int(en.get())
def countdown():
global be
if be >= 0:
mins, secs = divmod(be, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
label['text'] = timer
root.after(1000, countdown)
be -= 1
root = tk.Tk()
label = tk.Label(root, text = '00:00', font = 'Helvetica 25')
label.pack()
en = tk.Entry(root)
en.pack()
be1 = en.get()
tk.Button(root, text = 'set', height = 3, width = 20, command = lambda: set1()).pack()
tk.Button(root, text = 'go', height = 3, width = 20, command = lambda: countdown()).pack()
root.mainloop()

Please give be a value on top of your code, for example
be = 0

Related

Hi, i am trying to do an app that counts your clicks using python, tkinter. The problem is that the buttons won't work. Can someone help me?

import tkinter as tk
counter = 0
def counter_label (label):
counter = 0
def count():
global counter
counter+=1
label.config(text = str(counter))
label.after(1000, count)
count()
root = tk.Tk()
root.geometry("250x200")
root.title("Vladuzz208 SRL")
label = tk.Label(root, text = "Cronometru", font = ('Arial', 18))
label.pack(padx = 20, pady = 20)
Cronometru = tk.Label (root, fg = "White")
Cronometru.pack(padx = 20, pady = 10)
counter_label(Cronometru)
def ambda():
print(counter)
button = tk.Button(root, text = "Memoreaza", width = 15, command = ambda)
button.pack()
root.mainloop()
Like #acw1668 mentioned you should move the counter inside ambda() however, it could also be simplified quite a bit and if you want your label to update correctly you should move that also. Maybe this will help.
import tkinter as tk
counter = 0
root = tk.Tk()
root.geometry("250x200")
root.title("Vladuzz208 SRL")
label = tk.Label(root, text = "Cronometru", font = ('Arial', 18))
label.pack(padx = 20, pady = 20)
def ambda():
global counter
counter+=1
print(counter)
label.config(text=counter)
button = tk.Button(root, text = "Memoreaza", width = 15, command = ambda)
button.pack()
root.mainloop()

Python tKinter - Is there a way to get rid of existing label before making a new count-up?

I've found a countdown code and modified it so it counts up to a given number. It all works, but every time I push the button to run the functions, the existing label stays there and the new one gets put on top. (If I pack them, they get put underneath each other). It's because they get created inside the function, but I can't seem to find a way around it.
It might be a newbie question, but I'm just trying to learn :)
Code:
import time
from tkinter import *
import threading
betongtrykk = Tk()
betongtrykk.geometry("400x300")
canvas = Canvas(
betongtrykk,
bg = "#FFFFFF",
height = 300,
width = 400,
bd = 0,
highlightthickness = 0,
relief = "ridge"
)
canvas.place(x = 0, y = 0)
utnyttelseres = 65
def cd(timer_label_obj,ts):
while ts < utnyttelseres:
timer_label_obj.config(text=ts)
ts+=1
timer_label_obj.place(x=100, y=150)
time.sleep(0.01)
if ts == utnyttelseres:
timer_label_obj.config(text=utnyttelseres)
def countup(t):
timer = Label(betongtrykk)
th = threading.Thread(target=cd,args=[timer,t])
th.start()
submitCountdown = Button(betongtrykk, padx=5, pady=5, text="Submit", font=("Arial", 20), command= lambda:countup(0))
submitCountdown.place(x= 100, y=100)
betongtrykk.mainloop()
You can use the <widget>.destroy() method on the Label widget once the countdown is complete. This method will delete the widget and remove it from the screen.
Corrected Code:
import time
from tkinter import *
import threading
betongtrykk = Tk()
betongtrykk.geometry("400x300")
canvas = Canvas(
betongtrykk,
bg = "#FFFFFF",
height = 300,
width = 400,
bd = 0,
highlightthickness = 0,
relief = "ridge"
)
canvas.place(x = 0, y = 0)
utnyttelseres = 65
def cd(timer_label_obj,ts):
while ts < utnyttelseres:
timer_label_obj.config(text=ts)
ts+=1
timer_label_obj.place(x=100, y=150)
time.sleep(0.01)
if ts == utnyttelseres:
timer_label_obj.config(text=utnyttelseres)
timer_label_obj.destroy()
def countup(t):
timer = Label(betongtrykk)
th = threading.Thread(target=cd,args=[timer,t])
th.start()
submitCountdown = Button(betongtrykk, padx=5, pady=5, text="Submit", font=("Arial", 20), command = lambda:countup(0))
submitCountdown.place(x= 100, y=100)
betongtrykk.mainloop()
Alternate Solution:
If you want the countdown label to be removed JUST before the next countdown starts, you can make timer a global variable and use the .destroy() method on it before creating the new countdown label in countup.
def cd(timer_label_obj,ts):
while ts < utnyttelseres:
timer_label_obj.config(text=ts)
ts+=1
timer_label_obj.place(x=100, y=150)
time.sleep(0.01)
if ts == utnyttelseres:
timer_label_obj.config(text=utnyttelseres)
def countup(t):
global timer
try:
timer.destroy()
except NameError:
pass
timer = Label(betongtrykk)
th = threading.Thread(target=cd,args=[timer,t])
th.start()

How to get the coordinate of a checkbox created by tkinter package on a screen

I created a graphical user interface that has 3 checkboxes by using the Checkbox class given in tkinter package. I want to retrieve the screen coordinate of each checkbox. I have been trying to use pyautogui.position() to retrieve the coordianates. However, those values seem wrong because when I used those coordinates for the pyautogui engine to click on the box, it did not click. Also it seems that the window contained the checkboxes does not let me to check the boxes, when I was debugging it. What would be other possible ways that I can fix these problems?
from tkinter import *
import SpeechToDictation as Std
import pyautogui
import time
def speech_to_dictation():
speech_inst = Std.SpeechToDictation()
dictation.append(speech_inst.read_audio())
def user_speech_to_dictation():
main_window = Tk()
button = Button(text='Recording')
button.pack()
# have a while true at here so that when the function executes, it quits out of the loop
button.config(command=speech_to_dictation)
main_window.mainloop()
class Test(Frame):
def __init__(self, parent=None, picks=[]):
Frame.__init__(self, parent)
self.vars = []
self.checkboxes = []
Label(self, text='Lab Works').grid(row=0, padx=10, pady=10)
i = 1
for pick in picks:
var = IntVar()
chk = Checkbutton(self, text=pick, variable=var)
chk.grid(row=i, pady=4, padx=10)
self.vars.append(var)
self.checkboxes.append(chk)
i += 1
def state(self):
return map((lambda var: var.get()), self.vars)
def full_screen(window):
width = window.winfo_screenwidth()
height = window.winfo_screenheight()
window.geometry("%dx%d" % (width, height))
def allstates():
print(list(lng.state()))
def make_test(window):
full_screen(window=root)
window.grid(row=1, column=0)
Button(root, text='Quit', command=root.quit).grid(row=10, padx=10, pady=10)
Button(root, text='Peek', command=allstates).grid(row=12, padx=10, pady=10)
if __name__ == '__main__':
# store dictation at dictation[]
dictation = []
user_speech_to_dictation()
is_string_complete = dictation[0]['text'][:8]
if is_string_complete == 'complete':
start_time = time.time() # returns number of seconds passed since epoch
max_loop_time = 1 # 1 seconds
while True:
if (time.time() - start_time) >= max_loop_time:
root = Tk()
lng = Test(root, ['Blood Count', 'Lipid Panel', 'Hemoglobin A1C'])
make_test(window=lng)
root.state('zoomed')
root.update()
x_position, y_position = pyautogui.position()
print(x_position, y_position)
max_loop_time = time.time() - start_time + max_loop_time
# Coordinate of each boxes: they seem wrong
locations = [(53, 158), (84, 228), (36, 302)]
blood_count_string = dictation[0]['text'][9:]
if blood_count_string == 'blood count':
x_coordinate = locations[0][0]
y_coordinate = locations[0][1]
pyautogui.click(x_coordinate, y_coordinate)
allstates()
root.destroy()
# quit the program after the window is destroyed
if max_loop_time > 2:
break
Here is a quick example of how to get the coordinates and click the checkbutton (simply use .winfo_rootx() and .winfo_rooty()):
import tkinter as tk
import pyautogui as pag
def click_btn():
x = check_btn.winfo_rootx()
y = check_btn.winfo_rooty()
pag.click(x, y)
root = tk.Tk()
check_btn = tk.Checkbutton(root, text='This will be clicked in 3 seconds')
check_btn.pack()
root.after(3 * 1000, click_btn)
root.mainloop()

Program not running as expected after clicking the "Start" button

Program was working fine until I added the Start button on the bottom. Program seems to be running properly except that the timer doesn't update. I would like the counter to start counting down as soon as the "Start" button is clicked in my program.
My code:
import time
import tkinter as tk
def DisplayCountdown():
# Time
m = 0
s = 3
print('Running DisplayCountdown function')
if m == 0 and s == 0:
count_down_display.configure(text='Stand up!')
elif s == 0:
s=59
m-=1
count_down_display.after(1000, DisplayCountdown)
else:
s-=1
countdown_display.configure(text='%s minutes %s seconds' % (m,s))
countdown_display.after(1000, DisplayCountdown)
# Window
window = tk.Tk()
window.title('Stand Up Timer')
window.configure(bg = 'black')
# Information label
start_label = tk.Label(window,
font = 'ariel 40',
bg = 'black',
fg = 'red',
text = 'Click the start button to begin the timer.')
start_label.grid(row = 0, column = 0)
# Display Countdown
countdown_display = tk.Label(window,
font = 'ariel 40',
bg = 'black',
fg = 'red',
text = 'Countdown displayed here!')
countdown_display.grid(row = 1, column = 0)
# Start button
start_button = tk.Button(window,
text='Start',
command=DisplayCountdown)
start_button.grid(row = 2, column = 0)
# Window main loop
window.mainloop()
You have a few things to correct here.
First these 2 lines:
m = 0
s = 3
They cannot be in the function like this. Basically every loop will always start off a m=0 s=3. So instead pass them into the function as arguments.
Next Update your command and after statements to use a lambda to pass the initial and new time variables.
Next get rid of all those comments. They are redundant. Good code does not need comments as it is very obvious what is going on. Comments are normally need for complex sections of code that may need explaining for your self or other down the road.
I don't like going to new lines after every argument for widgets. Its just messy IMO the way you have it now. I write everything on a single line unless we overreach PEP8 recommended line length then find a good spot to go to new line.
Working example:
import tkinter as tk
def display_countdown(m, s):
print('Running DisplayCountdown function')
if m == 0 and s == 0:
countdown_display.configure(text='Stand up!')
elif s == 0:
s = 59
m -= 1
countdown_display.after(1000, lambda: display_countdown(m, s))
else:
s -= 1
countdown_display.configure(text='%s minutes %s seconds' % (m, s))
countdown_display.after(1000, lambda: display_countdown(m, s))
window = tk.Tk()
window.title('Stand Up Timer')
window.configure(bg='black')
start_label = tk.Label(window, font='ariel 40', bg='black', fg='red',
text='Click the start button to begin the timer.')
countdown_display = tk.Label(window, font='ariel 40', bg='black', fg='red',
text='Countdown displayed here!')
start_button = tk.Button(window, text='Start',
command=lambda: display_countdown(0, 3))
start_label.grid(row=0, column=0)
countdown_display.grid(row=1, column=0)
start_button.grid(row=2, column=0)
window.mainloop()

Tkinter - For Loop too early

I have a code for a "Magic Mirror" where I want to display clock, title and news (in Japanese).
I have a whole code that works fine with a news code inside it - In Tkinter loop - news code takes whole messages with json, hide everything except of title, put them to the list and shows loop through it to show messages one by one. It works well in terminal, but I have a struggles to put it into Tkinter window loop - It loops through it and shows only the last news subject - I would like them all, one every 10 seconds, or so... Is there a way to do it please? I will be happy for every answer, thanks.
Here is THE Code
import tkinter as tk
from tkinter import *
startupscreen = tk.Tk()
startupscreen.title('Magic Mirror: Python Mod')
welcometext = tk.Label(startupscreen, font = ('caviar dreams', 40), bg='black', fg='white')
startupscreen.configure(background='black')
startupscreen.overrideredirect(True)
welcometext.config(text='Mirror: Vuoristo Mod')
welcometext.pack(side=LEFT, padx= 120, pady=80)
# Gets the requested values of the height and widht.
windowWidth = startupscreen.winfo_reqwidth()
windowHeight = startupscreen.winfo_reqheight()
# Gets both half the screen width/height and window width/height
positionRight = int(startupscreen.winfo_screenwidth()/3 - windowWidth/2)
positionDown = int(startupscreen.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
startupscreen.geometry("+{}+{}".format(positionRight, positionDown))
startupscreen.update()
import time
from newsapi import NewsApiClient
import os
import feedparser
import json
from time import sleep
decrypt = list()
global iteration
global timecount
global repull
global sleep
iteration = 0
timecount = 0
repull = 0
sleep = 0
while True:
def tick(time1=''):
time2 = time.strftime("%H")
if time2 != time1:
time1 = time2
clock_frame.config(text=time2)
clock_frame.after(200, tick)
def tickk(time3=''):
time4 = time.strftime(":%M:%S")
if time4 != time3:
time3 = time4
clock_frame2.config(text=time4)
clock_frame2.after(200, tickk)
#This function waits for a certain amount of 'tocks' and then initiates 'newsheader' -function
def tock():
global timecount
global repull
global sleep
global decrypt
newstitle.after(200, tock)
if timecount < 20:
timecount +=1
else:
timecount = 0
newsheader()
if repull < 200:
repull +=1
if sleep < 800:
sleep+=1
else:
sleep = 0
motiondetector()
#This function iterates over the news headlines. Iteration is the news number, 'itemlist' brings out only the title.
def newsheader():
url = 'https://news.google.com/rss?hl=ja&gl=JP&ceid=JP:ja'
d = feedparser.parse(url)
news = list()
for i, entry in enumerate(d.entries, 1):
p = entry.published_parsed
sortkey = "%04d%02d%02d%02d%02d%02d" % (p.tm_year, p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec)
tmp = {
"title": entry.title,
#"link": entry.link,
"sortkey": sortkey
}
news.append(tmp)
news = sorted(news, key=lambda x: x['sortkey'])
myDict = {}
# HERE IS THE PROBLEM, I HAVE LIKE 30 news IN `frequency`, BUT IT SHOWS ONLY LAST ONE
for d in news:
c = d['title']
myDict[c] = myDict.get(c,0)+1
frequency = myDict.keys()
frequency = list(frequency)
for x in range(len(frequency)):
source.config(text=str(frequency[x]))
x += 1
root = tk.Tk()
root.title('Mirror')
lab = Label(root, text=" 日本", font = ('', 40), bg='black', fg='white')
lab.pack(anchor=SW, fill=X, padx=45)
masterclock = tk.Label(root)
masterclock.pack(anchor=NW, fill=X, padx=45)
masterclock.configure(background='black')
clock_frame = tk.Label(root, font = ('caviar dreams', 130), bg='black', fg='white')
clock_frame.pack(in_=masterclock, side=LEFT)
clock_frame2 = tk.Label(root, font = ('caviar dreams', 70), bg='black', fg='white')
clock_frame2.pack(in_=masterclock, side=LEFT, anchor = N, ipady=15)
newstitle = tk.Label(root, font = ('caviar dreams', 30), bg='black', fg='white')
newstitle.pack(side=BOTTOM, anchor=W, fill=X)
source = tk.Label(root, font = ('caviar dreams', 20), bg='black', fg='white')
source.pack(side=BOTTOM, anchor=W, fill=X)
newsheader()
tick()
tickk()
tock()
root.attributes("-fullscreen", True)
root.configure(background='black')
startupscreen.destroy()
root.mainloop()
This code use function display_next_item to get next element from list frequency and put in Label. And it use after() to do it again after 1 second. You can set 10 seconds but for test I use smaller value.
For tests I also had to removed fullscreen and newsapi (which I don't have installed)
import tkinter as tk
from tkinter import *
startupscreen = tk.Tk()
startupscreen.title('Magic Mirror: Python Mod')
welcometext = tk.Label(startupscreen, font = ('caviar dreams', 40), bg='black', fg='white')
startupscreen.configure(background='black')
startupscreen.overrideredirect(True)
welcometext.config(text='Mirror: Vuoristo Mod')
welcometext.pack(side=LEFT, padx= 120, pady=80)
# Gets the requested values of the height and widht.
windowWidth = startupscreen.winfo_reqwidth()
windowHeight = startupscreen.winfo_reqheight()
# Gets both half the screen width/height and window width/height
positionRight = int(startupscreen.winfo_screenwidth()/3 - windowWidth/2)
positionDown = int(startupscreen.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
startupscreen.geometry("+{}+{}".format(positionRight, positionDown))
startupscreen.update()
import time
#from newsapi import NewsApiClient
import os
import feedparser
import json
from time import sleep
decrypt = list()
global iteration
global timecount
global repull
global sleep
iteration = 0
timecount = 0
repull = 0
sleep = 0
while True:
def tick(time1=''):
time2 = time.strftime("%H")
if time2 != time1:
time1 = time2
clock_frame.config(text=time2)
clock_frame.after(200, tick)
def tickk(time3=''):
time4 = time.strftime(":%M:%S")
if time4 != time3:
time3 = time4
clock_frame2.config(text=time4)
clock_frame2.after(200, tickk)
#This function waits for a certain amount of 'tocks' and then initiates 'newsheader' -function
def tock():
global timecount
global repull
global sleep
global decrypt
newstitle.after(200, tock)
if timecount < 20:
timecount +=1
else:
timecount = 0
newsheader()
if repull < 200:
repull +=1
if sleep < 800:
sleep+=1
else:
sleep = 0
motiondetector()
#This function iterates over the news headlines. Iteration is the news number, 'itemlist' brings out only the title.
def newsheader():
url = 'https://news.google.com/rss?hl=ja&gl=JP&ceid=JP:ja'
d = feedparser.parse(url)
news = list()
for i, entry in enumerate(d.entries, 1):
p = entry.published_parsed
sortkey = "%04d%02d%02d%02d%02d%02d" % (p.tm_year, p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec)
tmp = {
"title": entry.title,
#"link": entry.link,
"sortkey": sortkey
}
news.append(tmp)
news = sorted(news, key=lambda x: x['sortkey'])
myDict = {}
for d in news:
c = d['title']
myDict[c] = myDict.get(c,0)+1
global frequency
frequency = list(myDict.keys())
def display_next_item():
global frequency
global next_index
next_index += 1
if next_index >= len(frequency):
next_index = 0
source.config(text=str(frequency[next_index]))
root.after(1000, display_next_item)
frequency = [] # value at start
next_index = 0 # value at start
root = tk.Tk()
root.title('Mirror')
lab = Label(root, text=" 日本", font = ('', 40), bg='black', fg='white')
lab.pack(anchor=SW, fill=X, padx=45)
masterclock = tk.Label(root)
masterclock.pack(anchor=NW, fill=X, padx=45)
masterclock.configure(background='black')
clock_frame = tk.Label(root, font = ('caviar dreams', 130), bg='black', fg='white')
clock_frame.pack(in_=masterclock, side=LEFT)
clock_frame2 = tk.Label(root, font = ('caviar dreams', 70), bg='black', fg='white')
clock_frame2.pack(in_=masterclock, side=LEFT, anchor = N, ipady=15)
newstitle = tk.Label(root, font = ('caviar dreams', 30), bg='black', fg='white')
newstitle.pack(side=BOTTOM, anchor=W, fill=X)
source = tk.Label(root, font = ('caviar dreams', 20), bg='black', fg='white')
source.pack(side=BOTTOM, anchor=W, fill=X)
newsheader()
tick()
tickk()
tock()
display_next_item() # <- start displaying
#root.attributes("-fullscreen", True)
root.configure(background='black')
startupscreen.destroy()
root.mainloop()
You need to use threading. And you can create a Repeating class or a Background class to perform your news reading every 10 seconds like this.

Categories

Resources