Cant use Tkinter button more than once - python

im kinda new to tkinter and while working on a school project ive stumbbled a problem, the button i use to change a label cant be used more than once.
here is the full code:
from tkinter import *
import random, time
dic = {}
def pDic(dic):
print(dic)
def add(dic):
org = orgEntry.get()
tran = tranEntry.get()
dic[org] = tran
tranEntry.delete(0,END)
orgEntry.delete(0,END)
return dic
def clear():
labOrg.grid_remove()
labTran.grid_remove()
orgEntry.grid_remove()
tranEntry.grid_remove()
save.grid_remove()
printDic.grid_remove()
train.grid_remove()
def pMain(dic):
global practiceBtn
clear()
i=0
kList = list(dic)
random.shuffle(kList)
practiceEntry = Entry(app)
practiceEntry.grid(row = 1 , column = 1)
labPractice = Label(app, text = "Enter translation for: " + kList[i] )
labPractice.grid(row = 0 , column = 1, padx = 200)
practiceBtn = Button(app, text = "Check", command = lambda : pLoop(i,kList,labPractice,dic,practiceEntry.get()))
practiceBtn.grid(row = 2 , column = 1)
def pLoop(i,kList, labPractice, dic ,entered):
if entered== dic[kList[i]]:
i+=1
next(i,kList,labPractice)
def next(i,kList,labPractice):
labPractice.grid_remove()
labPractice = Label(app, text = "Enter translation for: " + kList[i] )
labPractice.grid(row = 0 , column = 1, padx = 200)
app = Tk()
app.geometry('600x450+1000+60')
app.title("Dictionary")
labOrg = Label(app, text = "Enter Word")
labOrg.grid()
orgEntry = Entry(app)
orgEntry.grid(padx = 20)
labTran = Label(app, text = "Enter Translation")
labTran.grid(row = 0, column = 1, padx = 70)
tranEntry = Entry(app)
tranEntry.grid(row = 1, column = 1, padx = 70)
save = Button(app, text = "Save to dictionary", command = lambda : add(dic))
save.grid(row = 2 ,column = 1,columnspan = 1, pady=10, padx=50)
printDic = Button(app, text = "print dictionary", command = lambda : pDic(dic))
printDic.grid()
train = Button(app, text = "Train", command = lambda : pMain(dic))
train.grid(row = 2, pady = 20, padx = 50)
app.mainloop()
right now its kinda messy (and unfinished :p)but id be thankfull if you can run my code and tell me why the practiceBtn is not working.
the point is to get a dictionary as an input when keys are words and the values are the translation, then give the user a way to practice those words by cycling through all of them.

Related

Tkinter: How to prevent contents from previous searches appearing on a forthcoming search

currently working on an API-based F1 drivers' app using Python and Tkinter.
The issue I'm facing is that contents from previous searches appear on forthcoming content.
Visually, the issue can be best represented here, where the new content appears on top of the old content, which is no good.
To solve this problem, I know that logically, there should be some approach where when user presses search_button, the button should be attempting to clear the previous search's content in main_frame and then recreate main_frame with the new content.
Generally, it's not too difficult to clear content in a frame, since that's through using w_info and the .destroy() method, but I don't know how to recreate a frame with new content. In other words, I'm having trouble programming out the logic (perhaps the logic should be clearer or there should be different logic)
Here's the code:
#Go to
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
from tkinter import messagebox
import requests
import json
root = Tk()
root.geometry("800x300")
root.title("F1 Desktop Application")
root.iconbitmap("formula1_logo.ico")
#generate 2022 drivers-list [can scale to drivers-list by changing the]
drivers_list_request = requests.get("http://ergast.com/api/f1/2022/drivers.json")
#initialize empty-list
drivers_list = []
drivers_list_object = json.loads(drivers_list_request.content)
for elements in drivers_list_object["MRData"]["DriverTable"]["Drivers"]:
drivers_list.append(elements["givenName"] + " " + elements["familyName"])
# Update the Entry widget with the selected item in list
def check(e):
v= entry_box.get()
if v=='':
hide_button(menu)
else:
data=[]
for item in drivers_list:
if v.lower() in item.lower():
data.append(item)
update(data)
show_button(menu)
def update(data):
# Clear the Combobox
menu.delete(0, END)
# Add values to the combobox
for value in data:
menu.insert(END,value)
def fillout(event):
try:
entry_box.delete(0,END)
entry_box.insert(0,menu.get(menu.curselection()))
hide_button(menu)
#handle a complete deletion of entry-box via cursor double tap
except:
pass
def hide_button(widget):
widget.grid_remove()
def show_button(widget):
widget.grid()
def full_name():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}.json".format(lower_user_input))
response_object = json.loads(response.content)
name = response_object["MRData"]["DriverTable"]["Drivers"][0]["givenName"] + " " + response_object["MRData"]["DriverTable"]["Drivers"][0]["familyName"]
driver_name_label.configure(text = name)
def team():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/current/drivers/{}/constructors.json".format(lower_user_input))
response_object = json.loads(response.content)
team = response_object["MRData"]["ConstructorTable"]["Constructors"][0]["name"]
team_api = Label(main_frame, text = team, font = ("Arial", 10))
team_api.grid(row = 1, column = 1)
def driver_code():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}.json".format(lower_user_input))
response_object = json.loads(response.content)
code = response_object["MRData"]["DriverTable"]["Drivers"][0]["code"]
code_api = Label(main_frame, text = code, font = ("Arial", 10))
code_api.grid(row = 3, column = 1, sticky = W)
def nationality():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}.json".format(lower_user_input))
response_object = json.loads(response.content)
nationality = response_object["MRData"]["DriverTable"]["Drivers"][0]["nationality"]
nationality_api = Label(main_frame, text = nationality, font = ("Arial", 10))
nationality_api.grid(row = 2, column = 1, sticky = W)
def wins():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}/results/1.json".format(lower_user_input))
response_object = json.loads(response.content)
wins = response_object["MRData"]["total"]
wins_api = Label(main_frame, text = wins, font = ("Arial", 10))
wins_api.grid(row = 4, column = 1, sticky = W)
def poles():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}/qualifying/1.json".format(lower_user_input))
response_object = json.loads(response.content)
poles = response_object["MRData"]["total"]
poles_api = Label(main_frame, text = poles, font = ("Arial", 10))
poles_api.grid(row = 2, column = 3, sticky = W, padx = 15)
def podiums():
lower_user_input = grab_user_input()
#podiums is sum of 1st, 2nd, 3rd place finishes
#####DRY principle; let's reuse the code from wins()
######noticing how maybe should create a separate function which "places" the widget
#######for now, reuse the code
#1st place finishes
response = requests.get("http://ergast.com/api/f1/drivers/{}/results/1.json".format(lower_user_input))
response_object = json.loads(response.content)
#convert wins to int
wins = int(response_object["MRData"]["total"])
#2nd place finishes
response_ii = requests.get("http://ergast.com/api/f1/drivers/{}/results/2.json".format(lower_user_input))
response_ii_object = json.loads(response_ii.content)
response_ii_amount = int(response_ii_object["MRData"]["total"])
#3rd place finishes
response_iii = requests.get("http://ergast.com/api/f1/drivers/{}/results/3.json".format(lower_user_input))
response_iii_object = json.loads(response_iii.content)
response_iii_amount = int(response_iii_object["MRData"]["total"])
podiums = str(wins + response_ii_amount + response_iii_amount)
podiums_api = Label(main_frame, text = podiums, font = ("Arial", 10))
podiums_api.grid(row = 1, column = 3, padx = 15, sticky = W)
def championships():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/drivers/{}/driverStandings/1/seasons.json".format(lower_user_input))
response_object = json.loads(response.content)
championships = response_object["MRData"]["total"]
championships_api = Label(main_frame, text = championships, font = ("Arial", 10))
championships_api.grid(row = 3, column = 3, padx = 15, sticky = W)
def standing():
lower_user_input = grab_user_input()
response = requests.get("http://ergast.com/api/f1/current/drivers/{}/driverStandings.json".format(lower_user_input))
response_object = json.loads(response.content)
position = response_object["MRData"]["StandingsTable"]["StandingsLists"][0]["DriverStandings"][0]["position"]
points = response_object["MRData"]["StandingsTable"]["StandingsLists"][0]["DriverStandings"][0]["points"]
standing = "{} ({} pts)".format(position, points)
standing_api = Label(main_frame, text = standing, font = ("Arial", 10))
standing_api.grid(row = 4, column = 3, padx = 15, sticky = W)
def grab_user_input():
user_input = entry_box.get()
lower_user_input = user_input.lower().split(" ")[1]
return lower_user_input
def search():
#slow run-time is simply due to the multiple api calls made
#perhaps less-so due to not completely following DRY principles
full_name()
team()
driver_code()
nationality()
wins()
poles()
podiums()
championships()
standing()
show_button(main_frame)
left_frame = LabelFrame(root, width = 275, height = 300)
left_frame.grid(row = 1, column = 0, sticky = SE)
left_frame.grid_propagate(False)
search_label = Label(left_frame, text = "Search Driver", font = ("Arial bold", 12))
search_label.grid(row = 0, column = 0, pady = 10)
entry_box = Entry(left_frame, bd = 5)
entry_box.grid(row = 1, column = 0, padx = 35, pady = 40)
entry_box.bind('<KeyRelease>',check)
search_button = Button(left_frame, text = "search", command = search)
search_button.grid(row = 1, column = 1, padx = 15)
menu= Listbox(left_frame, height = 7)
menu.grid(row = 2, column = 0)
menu.bind("<<ListboxSelect>>",fillout)
main_frame = LabelFrame(root, width = 575, height = 300)
main_frame.grid(row = 1, column = 1, sticky = SE)
main_frame.grid_propagate(False)
driver_name_label = Label(main_frame, text = "Driver", font = ("Arial", 15))
driver_name_label.grid(row = 0, column = 0,pady = 30)
team_label = Label(main_frame, text = "TEAM", font = ("Arial", 10))
team_label.grid(row = 1, column = 0, sticky = W)
nationality_label = Label(main_frame, text = "NATIONALITY", font = ("Arial", 10))
nationality_label.grid(row = 2, column = 0, sticky = W)
driver_code_label = Label(main_frame, text = "DRIVER CODE", font = ("Arial", 10))
driver_code_label.grid(row = 3, column = 0, sticky = W)
wins_label = Label(main_frame, text = "WINS", font = ("Arial", 10))
wins_label.grid(row = 4, column = 0, sticky = W)
podiums_label = Label(main_frame, text = "PODIUMS", font = ("Arial", 10))
podiums_label.grid(row = 1, column = 2, sticky = W, padx = 15)
poles_label = Label(main_frame, text = "POLES", font = ("Arial", 10))
poles_label.grid(row = 2, column = 2, sticky = W, padx = 15)
world_championships_label = Label(main_frame, text = "WORLD CHAMPIONSHIPS", font = ("Arial", 10))
world_championships_label.grid(row = 3, column = 2, padx = 15, sticky = W)
current_standing_label = Label(main_frame, text = "F1 2022 STANDING", font = ("Arial", 10))
current_standing_label.grid(row = 4, column = 2, padx = 15, sticky = W)
hide_button(menu)
hide_button(main_frame)
root.mainloop()
Would appreciate the help! If there are any follow-up questions for clarity, let me know!
Thanks, Safwan

First tkinter project ,trying to find a way to make my tkinter buttons change boolean values for future if statements

I couldnt seem to find a way to make my program realise that ive selected a button, so i changed the function of the celcius to farenheit to try to make it change a boolean value to determine what conversion the program is doing
def celcius_to_farenheit(_event = None):
c_to_f = True
f_to_c = False
the idea being later i can use if statments later in the end result function to find what conversion its doing and display results in the status bar
def end_result():
if c_to_f == True:
converted_temperature = (valid_temperature * 9/5) + 32
label_status.configure(text = converted_temperature, fg = "Orange")
currently i seem to have functions running without me pressing buttons as well, when start the program it immediatly goes to the error message ive created for input muct be numeric even if i havent pressed the celcius to farenheit button.
Any help regarding how to propely have my celcius to farenheit and farenheit to celcius buttons confirm its a float and change a value to use for determining which calculation its using would be helpfull. Knowing why the error message comes up automatically is a bonus.
Below is my code thank you for your time and help.
import sys
from tkinter import *
from tkinter.tix import *
c_to_f = True
def clear_reset(_event = None):
entry_temperature.delete(0, END)
label_status.configure(text = "All data cleared", fg = "Orange")
def end_program(_event = None):
sys.exit()
def convert_temp(_event = None):
try:
valid_temperature = float(entry_temperature.get())
except:
label_status.configure(text = "Input must be numeric", fg = "Orange")
def end_result():
if c_to_f == True:
converted_temperature = (valid_temperature * 9/5) + 32
label_status.configure(text = converted_temperature, fg = "Orange")
def celcius_to_farenheit(_event = None):
c_to_f = True
f_to_c = False
def farenheit_to_celcius(_event = None):
f_to_c = True
c_to_f = False
window = Tk()
window.geometry("550x200")
window.resizable(False, False)
window.title("Temperature Conversion")
tooltip = Balloon(window)
label_input_Temperature = Label(text = "Temperature",fg = "Green")
label_input_Temperature.grid(row= 0, column=0)
entry_temperature = Entry(window, bg = "light blue" )
entry_temperature.grid(row=0, column=1)
temp_button_c_to_f = Button(window, text = "Celcius to Farenheit", command = celcius_to_farenheit)
temp_button_c_to_f.grid(row = 1, column=0)
window.bind('<Shift-c>', celcius_to_farenheit)
tooltip.bind_widget(temp_button_c_to_f, msg = "Shift + C")
temp_button_f_to_c = Button(window, text = "Farenheit to Celcius")
temp_button_f_to_c.grid(row = 1, column = 1 )
conversion_button = Button(window, text = "Convert", command = convert_temp)
conversion_button.grid(row = 2, column = 0,padx =0 )
window.bind('<Enter>', convert_temp)
tooltip.bind_widget(conversion_button, msg = "Enter")
clear_button = Button(window, text = "Clear", command = clear_reset)
clear_button.grid(row = 2, column = 1)
window.bind('<Control-c>', clear_reset)
tooltip.bind_widget(clear_button, msg = "Ctrl + C")
exit_button = Button(window, text = "Exit")
exit_button.grid(row = 2, column = 2, padx = 20, pady = 20)
window.bind('<Control-x>', end_program)
tooltip.bind_widget(exit_button, msg = "Ctrl + X")
label_status = Label(window, width = 50, borderwidth = 2, relief= RIDGE,bg= "Grey" )
label_status.grid(row = 4, column = 1)
tooltip.bind_widget(label_status, msg = "Displays results / error messages")
label_status.configure(text = "Enter in your temperature and select your conversion", fg = "Orange")
window.mainloop()

Create event log list from tkinter button presses

This is my first venture into tkinter programming, so far I have the following code that increases or decreases a number by pressing either button. As you may notice I have started adding an update definition that I'd like to update a results table with the label value each time a button is pressed. I've recently found the lambda expression to add two commands to each button press but can't find an example to build the list:
import tkinter as tk
window = tk.Tk()
def increase():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value + 1}"
def decrease():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value - 1}"
def update():
result_table = []
window.rowconfigure(0, minsize = 100, weight = 1)
window.columnconfigure([0,1,2], minsize = 100, weight = 1)
btn_decrease = tk.Button(master = window, text = "-", command = lambda:[decrease(), update()], bg = 'red', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = lambda:[increase(), update()], bg = 'green', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
, bg = 'black', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = increase, bg = 'red', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
I'd like to add a graph of the count to the display ultimately. Any help greatly appreciated.
Matt

Tkinter get() function is not returning anything [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 3 years ago.
I am trying to write a program using a tkinter GUI to calculate a few things. My get() function isn't working and I'm not sure why
from tkinter import *
from math import *
root = Tk()
v = 0
l = 0
w = 0
t1 = 0
t0 = 0
label1 = Label(root, text = "Enter value for length (mm) :").grid(columnspan = 2, sticky = "E")
length = Entry(root).grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume (mm^2) :").grid(columnspan = 2, sticky = "E")
volume = Entry(root).grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder (mm) :").grid(columnspan = 2, sticky = "E")
thickness = Entry(root).grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature (K) :").grid(columnspan = 2, sticky = "E")
st_T = Entry(root).grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature (K) :").grid(columnspan = 2, sticky = "E")
end_T = Entry(root).grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
answer = StringVar()
labelans = Label(root, textvariable = answer).grid(columnspan = 3,)
answer.set("Answer = ")
def area_circle():
global answer
answer = v / l
print(answer)
Button(root, text = "Submit", command = save()).grid(row = 6, column = 0)
root.mainloop()
Obviously there are variables i'm not using yet but im trying to get the first part right first.
For v the error displayed is:
Message='NoneType' object has no attribute 'get'
The Grid geometry manager puts the widgets in a 2-dimensional table.
The master widget is split into a number of rows and columns, and each
“cell” in the resulting table can hold a widget.
What is important Grid() is returning NoneValue
if you are doing like:
length = Entry(root).grid(row = 0, column = 2)
in your variable length you will have NoneValue
you should do it like :
length = Entry(root)
length.grid(row = 0, column = 2)
your code:
label1 = Label(root, text = "Enter value for length (mm) :")
label1.grid(columnspan = 2, sticky = "E")
length = Entry(root)
length.grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume (mm^2) :")
label2.grid(columnspan = 2, sticky = "E")
volume = Entry(root)
volume.grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder (mm) :")
label3.grid(columnspan = 2, sticky = "E")
thickness = Entry(root)
thickness.grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature (K) :")
label4.grid(columnspan = 2, sticky = "E")
st_T = Entry(root)
st_T.grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature (K) :")
label5.grid(columnspan = 2, sticky = "E")
end_T = Entry(root)
end_T.grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
answer = StringVar()
labelans = Label(root, textvariable = answer).grid(columnspan = 3,)
answer.set("Answer = ")
def area_circle():
global answer
answer = v / l
print(answer)
Button(root, text = "Submit", command = save()).grid(row = 6, column = 0)
root.mainloop()
output:
The command argument should be a callback, not the actual call:
Button(root, text="Submit", command=save).grid(row=6, column=0)

How do i make a continue button? Python, tkinter

I want to make a button in my widget that when I press it, it proceeds to the next lines of code, and closes the existing widget of where the button is.
from tkinter import *
root = Tk()
Label(root, text = "Childs First name").grid(row = 0, sticky = W)
Label(root, text = "Childs Surname").grid(row = 1, sticky = W)
Label(root, text = "Childs Year of Birth").grid(row = 2, sticky = W)
Label(root, text = "Childs Month of Birth").grid(row = 3, sticky = W)
Label(root, text = "Childs Day of Birth").grid(row = 4, sticky = W)
Fname = Entry(root)
Sname = Entry(root)
x = Entry(root)
y = Entry(root)
z = Entry(root)
Fname.grid(row = 0, column = 1)
Sname.grid(row = 1, column = 1)
x.grid(row = 3, column = 1)
y.grid(row = 2, column = 1)
z.grid(row = 4, column = 1)
button1 = Button(root, text = "Quit", command = root.quit, bg = "Grey", fg = "White", width = 12).grid(row = 5, column = 0, sticky = W)
def save():
Fname_value = Fname.get()
Sname_value = Sname.get()
x_value = x.get()
y_value = y.get()
z_value = z.get()
save()
mainloop()
Sorry for this late answer. To make a 'continue' button:
continue_button = tk.Button(frame,text='continue',command=func)
continue_button.config(width=width_continue_button)
# set the coordinates as you want. here 2,6 for the example
continue_button.grid(row=2,column=6,padx=width_continue_grid)
then you have to write the function 'func' to fulfill your needs.
hope this helps

Categories