Tkinter(python) code crashing without any errors - python

This is the code that i was trying to execute and it works good when i click on button for 55 times but on the 56 attempt it crashes. I am not able to understand why is it so. please help why it is crashing and how to solve this. I was trying to make a tambola board using tkinter. and should i use tkinter
from tkinter import *
import random
main_var = []
done_var = []
for a in range(1, 91):
main_var.append(a)
def board():
increas = 1
for x in range(10, 495, 55):
for y in range(10, 700, 70):
frame = Frame(
master=window,
relief=RAISED,
borderwidth=2,
bg="orange"
)
frame.place(x=y, y=x)
num_label = Label(master=frame, text=increas, borderwidth=2, bg="orange", fg="white", height=3,
width=9)
num_label.pack()
increas += 1
def num_generate():
random_num = random.choice(main_var)
num.set(random_num)
print(random_num)
main_var.remove(random_num)
done_var.append(random_num)
increas = 1
for x in range(10, 495, 55):
for y in range(10, 700, 70):
if increas in done_var:
frame = Frame(
master=window,
relief=RIDGE,
borderwidth=2,
bg="green"
)
frame.place(x=y, y=x)
num_label = Label(master=frame, text=increas, borderwidth=2, bg="green", fg="white", height=3,
width=9)
num_label.pack()
increas += 1
else:
frame = Frame(
master=window,
relief=RAISED,
borderwidth=2,
bg="orange"
)
frame.place(x=y, y=x)
num_label = Label(master=frame, text=increas, borderwidth=2, bg="orange", fg="white", height=3,
width=9)
num_label.pack()
increas += 1
# initialising
window = Tk()
window.geometry("1000x1000")
window.title("Tambola Game")
# for adding values from 1 to 90
# board function
board()
# Number Generator and marking on board
num = StringVar()
num_generate = Button(text="Generate", height=3, width=70, bg="red", fg="white", command=num_generate)
num_generate.place(x=770, y=500)
Label(textvariable=num, fg="dark blue", font="Algerian 200 bold").place(x=855, y=100)
# Orange = Not done, Green = Done
user_tell = Frame(relief=GROOVE, borderwidth=2)
user_tell.place(x=10, y=550)
label = Label(user_tell, text="PENDING NUMBERS", bg="Orange", width=25, fg="black", font="Verdana")
label.pack()
label = Label(user_tell, text="CALLED NUMBERS", bg="green", width=25, fg="black", font="Verdana")
label.pack()
# offers menu
window.mainloop()

It is not crashing without an error, it is raising the following exception : Cannot choose from an empty sequence.
This means that the main_var is empty (you have removed every element from it). You should check for it before trying to remove an element :
def num_generate():
if len(main_var) > 0:
random_num = random.choice(main_var)
num.set(random_num)
print(random_num)
main_var.remove(random_num)
else:
# do something else

Related

Values not stored in Tkinter Variables

In my code, I have tried to get the user input through text fields, store them in variables and finally print them in a tabular form.
The problem I am facing is that none of the values I enter through the text fields get displayed; when I try printing the variables, they come up empty.
Here's part of my code:
# SPASC
from tkinter import *
import tkinter as tk
import tkinter.ttk as tktrv
root = tk.Tk()
root.title("SPASC")
root.geometry("410x400")
lb1 = Label(root, text="SPASC \n Welcomes You !!!", fg="red", bg="sky blue"
, font=('Arial Black', 20), width=22, anchor=CENTER)
lb2 = Label(root, text="What would you like to compare?",
font=('Arial', 18), anchor=CENTER)
space1 = Label(root, text="\n\n")
lb1.grid(row=0)
lb2.grid(row=5)
space1.grid(row=1)
hpw, mil = StringVar(), StringVar()
def bt_cars():
w1 = Toplevel()
w1.title("Choose Features")
w1.geometry("430x200")
lb3 = Label(w1, text="Choose features for comparison", bg="yellow"
, font=('Arial Black', 18), width=25)
lb4 = Label(w1, text=" ", anchor=CENTER)
fr1 = LabelFrame(w1, width=20, padx=100)
hpw_cb = Checkbutton(fr1, text="Horsepower", variable=hpw, anchor='w', onvalue="Horsepower", offvalue="")
hpw_cb.grid()
hpw_cb.deselect()
mil_cb = Checkbutton(fr1, text="Mileage", variable=mil, anchor='w', onvalue="Mileage", offvalue="")
mil_cb.grid()
mil_cb.deselect()
var_stor = [hpw, mil]
print(hpw)
print(mil)
var_fill = []
for itr1 in var_stor:
if itr1 != "":
var_fill.append(itr1)
print(var_fill)
def car_1():
name1 = StringVar()
c1 = Toplevel()
c1.title("Car 1")
c1.geometry("430x200")
car1_lb1 = Label(c1, text="Car Name:")
name1_ifl = Entry(c1)
name1 = name1_ifl.get()
elm_var_fill = len(var_fill)
ct1 = 0
car1_val = []
for itr2 in var_fill:
if ct1 == elm_var_fill:
break
lb5 = Label(c1, text=itr2.get())
#Creating text field
ftr1_ifl = Entry(c1)
car1_ftr = ftr1_ifl.get()
car1_val.append(car1_ftr)
car1_ftr = None
lb5.grid(row=ct1 + 2, column=1)
ftr1_ifl.grid(row=ct1 + 2, column=2)
ct1 += 1
print(car1_val)
def display():
dp = Toplevel()
dp.title("Results")
dp.geometry("500x200")
car1_pt = 0
car2_pt = 0
car_tree = tktrv.Treeview(dp)
car_tree["columns"] = ("car1col")
car_tree.column("#0", width=120, minwidth=30)
car_tree.column("car1col", width=120, minwidth=30)
car_tree.heading("#0", text="Features" )
car_tree.heading("car1col", text=str(name1))
car_tree.pack()
c1.withdraw()
print(var_fill)
done1_bt = Button(c1, text="Continue", command=display)
name1_ifl.grid(row=0, column=2)
car1_lb1.grid(row=0, column=1)
done1_bt.grid(row=5,column=1)
w1.withdraw()
done_bt = Button(w1, text="Done", command=car_1)
done_bt.grid(row=3, column=1)
lb3.grid(row=0, column=1)
lb4.grid(row=1, column=1)
fr1.grid(row=2, column=1)
root.withdraw()
bt1 = Button(root, text="CARS", width=5, font=('Calibri', 15), command=bt_cars)
bt1.grid(row=7)
space2 = Label(root, text="\n\n")
space2.grid(row=6)
root.mainloop()
I am facing trouble with the variables named: hpw, mil, name1.
Any help would be welcome.
NOTE:- Please excuse the amount of code; I wanted others to replicate the error and see it for themselves
For the variables hpw and mil, these variables are empty strings that's why you are not getting any value from those checkboxes. To get values from the checkboxes replace these lines of code:
var_stor = [hpw, mil]
with
var_stor = [hpw_cb.cget('onvalue'), mil_cb.cget('onvalue')]
since you want the onvalue then you must use cget() method to access those values.
also, replace
lb5 = Label(c1, text=itr2.get())
with
lb5 = Label(c1, text=itr2)
because now you have required values (not objects) in a list, so just need to access those values.
For the variable name1 you can use #BokiX's method.
The problem is you are using get() wrong. You cannot use get() right after Entry() because as soon as entry is created it's getting the input before the user can even input something.
Use this code:
def get_input(text):
print(text)
e = Entry(root)
e.pack()
b = Button(root, text="Print input", command=lambda: get_input(e.get()))
b.pack()
Now get() method will not be executed before you click the button.

How to update a variable on keypress with tkinter?

I am trying to modify some code to work for me.
I have a running application with tkinter and I can update both scores (blue and red) when I am pressing the buttons, but I want to find a way how to do this via keypress ? For example to increase the score for the reds when pressing "r" and increase the score for the blue when pressing "b"
Tried different things from google but without any luck.
Could someone have a look and give me some hints?
import tkinter as tk
from time import sleep
window = tk.Tk()
window.configure(bg='black')
window.geometry('1024x600')
window.overrideredirect(True)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
scoreRed = 0
scoreBlue = 0
global BlueWonBoolean
global RedWonBoolean
BlueWonBoolean = False
RedWonBoolean = False
RedText = tk.StringVar()
BlueText = tk.StringVar()
RedText.set(str(scoreRed))
BlueText.set(str(scoreBlue))
def addBlue():
global scoreBlue
scoreBlue += 1
BlueText.set(str(scoreBlue))
if scoreBlue == 21:
global BlueWonBoolean
BlueWonBoolean = True
print("\nBlue Won!!!\nBLUE | RED\n " + str(scoreBlue) + " : " + str(scoreRed))
global BlueWon
BlueWon = tk.Label(text="Blue Won!!!",
foreground="white",
background="black",
width=10,
height=10)
BlueWon.pack(side=tk.TOP, fill=tk.X)
def addRed():
global scoreRed
scoreRed += 1
RedText.set(str(scoreRed))
if scoreRed == 21:
global RedWonBoolean
RedWonBoolean = True
print("\nRed Won!!!\nRED | BLUE\n" + str(scoreRed) + " : " + str(scoreBlue))
global RedWon
RedWon = tk.Label(text="Red Won!!!",
foreground="white",
background="black",
width=10,
height=10)
RedWon.pack(side=tk.TOP, fill=tk.X)
def resetScore():
global scoreRed
global scoreBlue
global BlueWonBoolean
global RedWonBoolean
scoreRed = 0
scoreBlue = 0
RedText.set(str(scoreRed))
BlueText.set(str(scoreBlue))
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
if BlueWonBoolean == True:
BlueWon.destroy()
BlueWonBoolean = False
elif RedWonBoolean == True:
RedWon.destroy()
RedWonBoolean = False
BlueButton = tk.Button(window, text="Blue Point", bg="white", fg="yellow", width=30, height=15, command=addBlue)
RedButton = tk.Button(window, text="Red Point", bg="red", fg="black", width=30, height=15, command=addRed)
ResetButton = tk.Button(window, text="Reset", width=10, height=3, command=resetScore)
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
def Quit():
exit()
while True:
try:
BlueLabel = tk.Label(
textvariable=BlueText,
foreground="white",
background="black",
width=10,
height=5
)
RedLabel = tk.Label(
textvariable=RedText,
foreground="white",
background="black",
width=10,
height=5
)
BlueButton = tk.Button(window, text="Blue Point", bg="black", fg="WHITE", width=30, height=15, command=addBlue)
RedButton = tk.Button(window, text="Red Point", bg="black", fg="WHITE", width=30, height=15, command=addRed)
ResetButton = tk.Button(window, text="Reset", bg="black", fg="WHITE", width=10, height=3, command=resetScore)
quitButton = tk.Button(window, text="Quit ", bg="black", fg="WHITE", command=Quit)
# image = tk.PhotoImage(file="cornHole.png")
# imageLabel = tk.Label(image=image)
BlueLabel.pack(side=tk.LEFT, fill=tk.X)
RedLabel.pack(side=tk.RIGHT, fill=tk.X)
BlueButton.pack(side=tk.LEFT, fill=tk.X)
RedButton.pack(side=tk.RIGHT, fill=tk.X)
# imageLabel.pack(side=tk.TOP, fill=tk.X)
quitButton.pack(side=tk.TOP, fill=tk.X)
ResetButton.pack(side=tk.TOP, fill=tk.X)
window.bind("<Escape>", exit)
window.mainloop()
except:
exit()
You can use keybindings to run the function when a key is pressed
window.bind("b", addblue )
Here are a website and a video explaining them further
https://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
https://www.youtube.com/watch?v=GLnNPjL1U2g
Hi #Veleslav Panov and welcome to Stack Overflow! You can use the .bind()method available in tkinter t achieve this task. For example, imagine that you want to update variable on pressing the Enter or the Return key. Then use this:
def function_name(*args):
variable_name +=1
#say the updation to be done here
name_of_window.bind("<Return>", function_name)
Note: Instead of *args, you can use any variable name, the only thing needed is that there should be at least one variable
You can use us .bind() to bind any key to any function, the only requirment is that the function will have some argument, for example 'event'.
def function(event):
#Do something
window.bind("<Return>", function)
This way, every time the button (in this case Enter) is pressed, the function will be called. In your case you would bind 2 buttons, 'r' and 'b', to 2 functions to add score to each of the sides.
Here is a link with some examples:
https://www.geeksforgeeks.org/python-binding-function-in-tkinter/

Why isn't my Tkinter button image updating?

You may recognize this code. I'm steadily improving it :)
This time I'm stuck trying to figure out why a button image will not update after I click on it. I'm not getting any errors, so I'm not sure how to debug this.
This is my code:
import tkinter as tk
from tkinter import simpledialog,filedialog,colorchooser,messagebox,Frame,Button
from PIL import ImageTk, Image
root = tk.Tk()
load1 = Image.open("example.jpg")
root.render1 = ImageTk.PhotoImage(load1)
canv_1 = tk.Canvas(root, bg="gray")
canv_1.grid_rowconfigure(0, weight=1)
canv_1.grid_columnconfigure(6, weight=2)
canv_1.grid(row=0, column=0, sticky="news")
canv_1.grid(row=1, column=0, sticky="news")
labels = ["Image", "Chapter #", "Chapter Title", "Step", "Slide", "Sequence Step", "Instructions"]
root.label_wid = []
font1 = ("arial", 15, "bold")
for i in range(len(labels)):
root.label_wid.append(tk.Label(canv_1, font=font1, relief="raised", text=labels[i]).grid(row=0, column=i,
sticky="we"))
def exportCode():
print("code exported")
a = instruction_col[0].get('1.0','10.0')
print(a)
print("end")
root.images = [
ImageTk.PhotoImage(Image.open("example.jpg"))
for y in range(1,6)
]
def change_img(y):
#print(y)
#print(len(root.images))
root.img1 = filedialog.askopenfilename()
root.load_img1 = Image.open(root.img1)
root.render_img1 = ImageTk.PhotoImage(root.load_img1)
image_col[y]['image'] = root.render_img1
print(image_col[y]['image'])
print(image_col[y-1]['image'])
print(root.render_img1)
c1 = "#a9d08e"
c2 = "#8dd1bf"
image_col = [
tk.Button(
canv_1,
image=root.render1,
relief="raised",
bg="light gray",
command = lambda: change_img(y),
)
for y in range(0, 5)
]
for y, image_cell in enumerate(image_col, 1):
image_cell.grid(row=y, column=0, sticky='news')
instruction_col = [
tk.Text(
canv_1,
bg="white",
wrap="word",
font=("arial",15), width=20, height=10)
for y in range(0, 5)
]
for y, image_cell in enumerate(instruction_col, 1):
image_cell.grid(row=y, column=6, sticky='news')
# ================================================================================================
bt1 = tk.Button(canv_1, text="Export", font=font1, command=exportCode).grid(row=0, column=7)
load2 = Image.open("scroll-up.png")
root.render2 = ImageTk.PhotoImage(load2)
load3 = Image.open("scroll-down.png")
root.render3 = ImageTk.PhotoImage(load3)
scroll_up = tk.Button(canv_1, image=root.render2).grid(row=1, column=7, rowspan=2) # , sticky="n")
scroll_up = tk.Button(canv_1, image=root.render3).grid(row=3, column=7, rowspan=2) # , sticky="s")
root.mainloop()
It was working fine before when I wasn't using a list, and I manually defined each widget as RxCx (Row #, Column #) but now that I simplified my code with lists image_col & instruction_col, I'm having trouble with the change_image(y) function
Below is the function I was previously using:
it worked fine, but I took up a lot of lines manually defining each widget
def change_img(row):
if row == 1:
root.img1 = filedialog.askopenfilename()
root.load_img1 = Image.open(root.img1)
root.render_img1 = ImageTk.PhotoImage(root.load_img1)
R1C0['image']=root.render_img1
if row == 2:
# etc...

Tkinter Text widget returns ".!frame3.!frame3.!frame.!text" instead of appropriate values

I'm currently working on a project where you scan bar codes and it implements the result into an excel file. I am using tkinter to make my GUI, however, when I try to get the values from a text widget it returns the value ".!frame3.!frame3.!frame.!text". how can I fix this to get the appropriate values?
here is my code so far
import tkinter as tk
from tkinter import *
root = tk.Tk(className = "Tool Manager")
root.configure(bg='#C4C4C4')
root.title('Main Screen')
root.geometry("800x600")
main = Frame(root, bg='#C4C4C4', width = 800, height = 600)
#This is the contents of the Main Frame (screen 1)
frame_pad1 = Frame(main, bg='#C4C4C4')
frame_1 = Frame(main,bg='#C4C4C4')
frame_2 = Frame(main, bg='#C4C4C4')
frame_3 = Frame(main, bg='#C4C4C4')
min = Frame(root, bg = 'GREEN')
#mout stuffs
mout = Frame(root, bg = '#C4C4C4')
outframe_pad1 = Frame(mout, bg='#C4C4C4')
outframe_1 = Frame(mout, bg='#C4C4C4')
outframe_2 = Frame(mout, bg='#C4C4C4')
outframe_3 = Frame(mout, bg='#C4C4C4')
#code for changing screens
def raise_frame(frame):
frame.tkraise()
for frame in (main, min, mout):
frame.grid(row=1, column=1, sticky='news')
#sets frame weight for 3 rows (centers frames)
rows = 0
while rows < 3:
root.rowconfigure(rows, weight=1)
root.columnconfigure(rows,weight=1)
rows += 1
def commit_to_file():
ID = name.get()
out_list.get('1.0', 'end-1c')
print(out_list) #<----- THIS IS WHERE I'M RETURNING VALUES TO THE TERMINAL
def on_every_keyboard_input(event):
update_char_length(out_list)
#updating Line Length Information
def update_char_length(out_list):
string_in_text = out_list.get('1.0', '1.0 lineend')
string_length = len(string_in_text)
print(string_length)
if (string_length == 4):
out_list.insert(0.0, '\n')
out_list.mark_set("insert", "%d.%d" % (0,0))
#main screen formatting
area = PhotoImage(file="test.png")
areaLabel = Label(frame_1, image=area, bg='#C4C4C4')
areaLabel.pack(side=RIGHT)
mwLabel = Label(frame_2,text="this is only a test", font=("Airel", 20), bg='#C4C4C4')
mwLabel.pack(side=RIGHT)
out_button = Button(frame_3, text="Check Out", command=lambda:raise_frame(mout) , height=5, width=20, font=("Airel", 15))
out_button.pack(side=RIGHT, padx=20, pady = 4)
in_button = Button(frame_3, text="Check In", command=lambda:raise_frame(min), height=5, width=20, font=("Airel", 15))
in_button.pack(side=LEFT, padx=20, pady = 4)
#out screen formatting
name = Entry(outframe_1, font=("Airel", 15))
name.pack(side=RIGHT)
name_lbl = Label(outframe_1, text="ID Number", bg='#C4C4C4', font=("Airel", 15))
name_lbl.pack(side=LEFT)
outlist = Frame(outframe_2, bd=1, relief=SUNKEN)
outlist.pack(side=LEFT)
out_list = Text(outlist, height=30, width=40)
out_list.pack(side=RIGHT)
done_btn = Button(outframe_3, text="Done", command=commit_to_file, font=("Ariel", 15))
done_btn.pack(side=RIGHT, padx=20, pady=4)
#init to main screen
raise_frame(main)
#drawing objects for main screen
frame_pad1.pack(padx=1, pady=25)
frame_1.pack(padx=1,pady=1)
frame_2.pack(padx=10,pady=1)
frame_3.pack(padx=1, pady=80)
#drawing out screen
outframe_1.pack(padx=1, pady=1)
outframe_2.pack(padx=1,pady=1)
outframe_3.pack(padx=1, pady=1)
#calls line info update out screen
out_list.bind('<KeyRelease>', on_every_keyboard_input)
root.mainloop()
You are printing the command and not the value of it. Put the command in a variable and then print the variable.
Example: myVar = out_list.get("1.0", "end-1c") and then print(myVar)

How to get tkinter Spinbox's value?

I am trying to make a timer on python Tkinter. To set the timer, I am using spinboxes. But, I am having trouble getting the value of my spinboxes to be turned into the variables time_h, time_m and time_s.
I have tried .get() but it is not working. When I tried printing the variables I got NameError: name 'spin_h' is not defined.
from tkinter import *
window = Tk()
window.title("Timer")
window.geometry('350x200')
hour = 0
minute = 0
second = 0
timer = (str(hour) + ':' + str(minute) + ':' + str(second))
lbl = Label(window, text=timer, font=("Arial Bold", 50))
hour_s = 0
min_s = 0
sec_s = 0
def save_time():
time_h = spin_h.get()
time_m = spin_m.get()
time_s = spin_s.get()
def new_window():
set_time = Tk()
spin_h = Spinbox(set_time, from_=0, to=10, width=5)
spin_h.grid(column=1,row=0)
spin_m = Spinbox(set_time, from_=0, to=60, width=5)
spin_m.grid(column=3,row=0)
spin_s = Spinbox(set_time, from_=0, to=60, width=5)
spin_s.grid(column=5,row=0)
h_label = Label(set_time, text='h', font=("Arial Bold", 10))
h_label.grid(column=2, row=0)
m_label = Label(set_time, text='m', font=("Arial Bold", 10))
m_label.grid(column=4, row=0)
s_label = Label(set_time, text='s', font=("Arial Bold", 10))
s_label.grid(column=6, row=0)
set_button = Button(set_time, text="Set Time", command=save_time)
set_button.grid(column=3, row=2)
btn = Button(window, text="Set Time", command=new_window)
btn.grid(column=3, row=2)
lbl.grid(column=3, row=0)
window.mainloop()
spin_h is a variable local to the new_window() function and there cannot be accessed by the save_time() function. You could declare it a global variable at the beginning of new_window() to fix that. - #Martineau (just made it into an answer instead of a comment).
Thanks Martineau

Categories

Resources