How to Add up multiple entry in Tkinter - python

I work on a program that calculates the macros of each meal. You can enter a value in gram and it calculates for each aliment your intake. I would like now to add these values together when I push multiple buttons. Then I'll display the value somewhere and maybe I could do a graph after.
Here I show what my program looks like :
import tkinter as tk
def value_kiwi():
value = ent_quantity.get()
formula = (float(value)/100)
cal = 53
pro = 1.6
glu = 11.1
li = 0.3
Calories = (cal) * formula
Protéines = (pro) * formula
Glucides = (glu) * formula
Lipides = (li) * formula
lbl_cal["text"] =f"{Calories}"
lbl_prot["text"] = f"{Protéines}"
lbl_glu["text"] = f"{Glucides}"
lbl_lip["text"] = f"{Lipides}"
def value_banane():
value = ent_quantity.get()
formula = (float(value)/100)
cal = 90
pro = 1.5
glu = 20.1
li = 0
Calories = (cal) * formula
Protéines = (pro) * formula
Glucides = (glu) * formula
Lipides = (li) * formula
lbl_cal["text"] =f"{Calories}"
lbl_prot["text"] = f"{Protéines}"
lbl_glu["text"] = f"{Glucides}"
lbl_lip["text"] = f"{Lipides}"
window = tk.Tk()
window.title("Calculateur de Calories et Nutriments")
frm_entry = tk.Frame(master=window)
ent_quantity = tk.Entry(master=frm_entry, width=5)
ent_quantity.grid(row=1, column=0,)
lbl_cal = tk.Label(master=window)
lbl_cal.grid(row=1, column=1,)
lbl_prot = tk.Label(master=window)
lbl_prot.grid(row=1, column=2)
lbl_glu = tk.Label(master=window)
lbl_glu.grid(row=1, column=3)
lbl_lip = tk.Label(master=window)
lbl_lip.grid(row=1, column=4)
btn_kiwi = tk.Button(
master=window,
text="Kiwi",
command=value_kiwi,
)
btn_banane = tk.Button(
master=window,
text="Banane",
command=value_banane,
)
lbl_calories = tk.Label(master=window, text="Calories",)
lbl_proteines = tk.Label(master=window, text="Protéines")
lbl_glucides = tk.Label(master=window, text="Glucides")
lbl_lipides = tk.Label(master=window, text="Lipides")
lbl_fruits = tk.Label(master=window, text="Fruits")
frm_entry.grid(row=1, column=0, padx=10)
lbl_calories.grid(row=0,column=1, padx=5, sticky="w")
lbl_proteines.grid(row=0, column=2, padx=10)
lbl_glucides.grid(row=0, column=3, padx=10)
lbl_lipides.grid(row=0,column =4, padx=10)
lbl_fruits.grid(row=1,column =5, padx=10)
btn_kiwi.grid(row=2, column=5, pady=10)
btn_banane.grid(row=3, column=5, pady=10)
window.mainloop()

Ok, I think I improved Your code:
from tkinter import Tk, Button, Entry, Label
class MainWindow(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Nutrient calculator')
# entry
Label(self, text='Amount').grid(row=0, column=0)
self.amount = Entry(self, width=5, bg='light grey')
self.amount.grid(row=1, column=0)
# calories
Label(self, text='Calories').grid(row=0, column=1)
self.calories = Label(self)
self.calories.grid(row=1, column=1)
# proteins
Label(self, text='Proteins').grid(row=0, column=2)
self.proteins = Label(self)
self.proteins.grid(row=1, column=2)
# glucose
Label(self, text='Glucose').grid(row=0, column=3)
self.glucose = Label(self)
self.glucose.grid(row=1, column=3)
# lipids
Label(self, text='Lipids').grid(row=0, column=4)
self.lipids = Label(self)
self.lipids.grid(row=1, column=4)
# list of all labels
self.data_labels = [self.calories, self.proteins, self.glucose, self.lipids]
# error label for if no value is entered or it cannot be converted
self.error_label = Label(self, text='Use integer or float value!')
# stuff for adding multiple foods
self.do_add = False
self.nutrient_list = []
self.plus_btn = Button(self, text='Add', command=self.add)
self.plus_btn.grid(row=3, column=0, columnspan=4, sticky='nwes')
def display_values(self, value_list):
self.nutrient_list.append(value_list)
if len(self.nutrient_list) == 2 and not self.do_add:
self.nutrient_list.pop(0)
elif len(self.nutrient_list) > 2 and not self.do_add:
self.nutrient_list = [self.nutrient_list[-1]]
print(self.nutrient_list)
if self.do_add:
value_list = []
for i in range(len(self.nutrient_list[0])):
total_value = 0
for item in self.nutrient_list:
total_value += item[i]
value_list.append(total_value)
for text, label in zip(value_list, self.data_labels):
label.config(text=f'{text:.2f}')
self.do_add = False
def handle_value_error(self):
self.error_label.grid(row=2, column=0, columnspan=4)
def add(self):
self.do_add = True
self.amount.delete(0, 'end')
class Values:
def __init__(self, name, row, column, calories, proteins, glucose, lipids):
self.parent = root
self.name = name
self.row = row
self.column = column
self.calories = calories
self.proteins = proteins
self.glucose = glucose
self.lipids = lipids
self.stuff_list = [self.calories, self.proteins, self.glucose, self.lipids]
self.button = Button(self.parent, text=self.name, command=self.set_values)
self.button.grid(row=self.row, column=self.column, sticky='nwse')
def set_values(self):
value_list = []
value_ = self.parent.amount.get()
try:
formula = float(value_) / 100
self.parent.error_label.grid_forget()
for item in self.stuff_list:
item *= formula
value_list.append(item)
self.parent.display_values(value_list)
except ValueError:
self.parent.handle_value_error()
root = MainWindow()
kiwi = Values('Kiwi', 2, 4, calories=53, proteins=1.6, glucose=11.1, lipids=0.3)
banana = Values('Banana', 3, 4, calories=90, proteins=1.5, glucose=20.1, lipids=0)
root.mainloop()
it is not necessarily better however a few benefits from using this code are:
better organization (IMO) since it uses classes which make it pretty neat (however You have to have an understanding over them)
takes less space - what I mean is that now, to define a new food, You just have to initiate the Values class and give it the necessary arguments. You can take an example from the given instances.
possibly easier to expand (both because better organization and takes less space)
I edited the code so now it should have that functionality, the way it works is You choose an amount , then fruit and if You want to add more, press add button, then choose amount, press food and it will display the total so far, then again, if You want to add more press add and then put in an amount and press the fruit, currently the way to 'clear' is to press any food button and it should then reset the whole list and keep only the one that was just pressed and then repeat.

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.

Tkinter using foo.destroy() makes the gui blank

I'm trying to make a country quiz program.
I would like for the start GUI to completely be destroyed when the user clicks their difficulty they want to play.
However, I used foo.destroy() and the start GUI turns completely blank and doesn't disappear.
I tried using Toplevel() and while foo.destroy works the program opens up 2 guis when I run it.
from tkinter import *
from functools import partial
import csv
import random
import re
class Start:
def __init__(self):
# Color is light yellow for the background
background = "#FFF4C3"
# Start GUI
self.start_frame = Frame(padx=10, pady=10, bg=background)
self.start_frame.grid()
# Country Capital Quiz Heading row 0
self.capital_label = Label(self.start_frame, text="Country Capital Quiz",
font="Helvetica 30 bold", bg=background)
self.capital_label.grid(row=0)
# Sub text and Instructions for the game row 1
self.subtext_label = Label(self.start_frame, text="How well do you know world's capitals? \n\n"
"You'll be presented with 15 capitals from a list of 242 "
"capitals.\n "
"You'll need to match the capitals with their corresponding "
"country. \n\n "
"Please select the difficulty you wish to play.",
font="Arial 10", bg=background)
self.subtext_label.grid(row=1)
# to_game button frame row 2
self.to_game_frame = Frame(self.start_frame, bg=background)
self.to_game_frame.grid(row=2)
# Button Font
button_font = "Arial 15 bold"
# to_game buttons row 2.0
self.easy_button = Button(self.to_game_frame, text="Easy", font=button_font, bg="#99CCFF",
command=self.to_easy, height=2, width=13, borderwidth=2)
self.easy_button.grid(row=0, column=0, padx=10, pady=5)
self.hard_button = Button(self.to_game_frame, text="Hard", font=button_font, bg="#FFBAB8",
command=self.to_hard, height=2, width=13, borderwidth=2)
self.hard_button.grid(row=0, column=1, padx=10, pady=5)
# Help Button row 3
self.help_button = Button(self.start_frame, text="Help", font="Helvetica 10 bold", height=2, width=10,
borderwidth=3, command=self.help)
self.help_button.grid(row=3, pady=5)
def to_easy(self):
Easy()
self.start_frame.destroy()
def to_hard(self):
Hard()
self.start_frame.destroy()
def help(self):
get_help = Help(self)
get_help.help_text.configure(text="The quiz will present you with a capital \nYou must identify the "
"corresponding country.\n\nThere "
"are a total of 15 rounds.\n\n"
"Easy mode is a multiple choice quiz.\n"
"Hard mode you must type in the answer.\n\n"
"The answers can be case insensitive.\nHowever, they must have proper "
"spacing and spelling.")
class Help:
def __init__(self, partner):
background = "#FFF4C3"
# disable help button
partner.help_button.config(state=DISABLED)
# Sets up child window (ie: help box)
self.help_box = Toplevel()
# If users press 'x' cross at the top, closes help and 'releases' help button.
self.help_box.protocol('WM_DELETE_WINDOW', partial(self.close_help, partner))
# Set up GUI Frame
self.help_frame = Frame(self.help_box, bg=background)
self.help_frame.grid()
# Set up Help heading (row 0)
self.how_heading = Label(self.help_frame, text="Help / Information",
font=("Helvetica", "24", "bold",),
bg=background)
self.how_heading.grid(row=0)
# Help text (label, row 1)
self.help_text = Label(self.help_frame, text="", font="helvetica",
bg=background, justify=LEFT,wrap=350)
self.help_text.grid(row=1)
# Dismiss button (row 2)
self.dismiss_btn = Button(self.help_frame, text="Dismiss", width=10, bg="maroon", fg="white",
font="Helvetica" "10" "bold", command=partial(self.close_help, partner))
self.dismiss_btn.grid(row=2, pady=10)
def close_help(self, partner):
# Put help button back to normal...
partner.help_button.config(state=NORMAL)
self.help_box.destroy()
def to_quit():
root.destroy()
class Easy:
def __init__(self):
# Background color is light yellow
background = "#FFF4C3"
# Import the csv file, name of csv file goes here...
with open('country-capitals.csv', 'r') as f:
# make csv file into list
file = csv.reader(f)
next(f)
my_list = list(file)
# List to store the answers
self.game_history = []
# Initial Score
self.score = 0
# Amounts of games played
self.played = 0
# chooses four different countries / capitals from the list
question_ans = random.choice(my_list)
yes = random.choice(my_list)
no = random.choice(my_list)
ok = random.choice(my_list)
# Defining variables for the capitals and countries,
# question is the capital in question
# self.answer is the correct answer
# incorrect[1,2,3] are the incorrect countries.
self.question = question_ans[1]
self.answer = question_ans[0]
self.hint = question_ans[2]
incorrect1 = yes[0]
incorrect2 = no[0]
incorrect3 = ok[0]
# I made the button_list a list so the list can be randomized so that the answer button locations is always
# different.
button_list = [self.answer, incorrect1, incorrect2, incorrect3]
random.shuffle(button_list)
# Defining the randomized list to their corresponding buttons
self.top_left = button_list[0]
self.top_right = button_list[1]
self.bottom_left = button_list[2]
self.bottom_right = button_list[3]
# GUI Setup
self.game_box = Toplevel(bg=background)
self.game_frame = Frame(self.game_box, bg=background)
self.game_frame.grid()
self.game_box.protocol('WM_DELETE_WINDOW', to_quit)
# Capital Label row 0
self.capital_label = Label(self.game_frame, text=self.question,
font="Helvetica 15 bold", bg=background)
self.capital_label.grid(row=0)
# Label showing correct or incorrect row 1
self.answer_box = Label(self.game_frame, text="", font="Helvetica 12 italic", width=45, bg=background)
self.answer_box.grid(row=1)
# Setup grid for answer buttons row 2
self.top_answers_frame = Frame(self.game_box, width=50, height=50, bg=background)
self.top_answers_frame.grid(row=2, padx=5)
# width, wrap, font height for buttons
wt = 20
ht = 2
wr = 200
ft = "Helvetica 15"
# Top level answers buttons row 2.0
self.top_left_answer_button = Button(self.top_answers_frame, text=self.top_left,
font=ft, padx=5, pady=5, width=wt, height=ht, wrap=wr, bg="#EEE6D2",
command=lambda: self.reveal_answer(self.top_left))
self.top_left_answer_button.grid(column=0, row=0, padx=5, pady=5)
self.top_right_answer_button = Button(self.top_answers_frame, text=self.top_right,
font=ft, padx=5, pady=5, width=wt, height=ht, wrap=wr, bg="#EEE6D2",
command=lambda: self.reveal_answer(self.top_right))
self.top_right_answer_button.grid(column=1, row=0, padx=5, pady=5)
# Bottom level answers buttons row 2.1
self.bottom_left_answer_button = Button(self.top_answers_frame, text=self.bottom_left,
font=ft, padx=5, pady=5, width=wt, height=ht, wrap=wr, bg="#EEE6D2",
command=lambda: self.reveal_answer(self.bottom_left))
self.bottom_left_answer_button.grid(column=0, row=1, padx=5, pady=5)
self.bottom_right_answer_button = Button(self.top_answers_frame, text=self.bottom_right,
font=ft, padx=5, pady=5, width=wt, height=ht, wrap=wr, bg="#EEE6D2",
command=lambda: self.reveal_answer(self.bottom_right))
self.bottom_right_answer_button.grid(column=1, row=1, padx=5, pady=5)
# Label for the score and games played row 3
self.score_label = Label(self.game_box, text="{} correct, {} rounds played".format(self.score, self.played),
bg=background)
self.score_label.grid(row=3)
# Button frames for next and hint button row 4
self.button_frame = Frame(self.game_box, bg=background)
self.button_frame.grid(row=4)
# The hint button to get the hint for this country row 0 column 0
self.hint_button = Button(self.button_frame, text="Hint", command=self.to_hint, width=7,
font="Helvetica 10 bold")
self.hint_button.grid(row=0, column=0, padx=5,pady=8)
# The Next button to proceed to the next round row 0 column 1
self.next_button = Button(self.button_frame, text="Next",
command=lambda: self.to_next(my_list, self.game_history), width=7,
font="Helvetica 10 bold")
self.next_button.grid(row=0, column=1, padx=5,pady=8)
# Disable the next button initially,
self.next_button.config(state=DISABLED)
def reveal_answer(self, location):
# Disable all the buttons
self.top_left_answer_button.config(state=DISABLED)
self.top_right_answer_button.config(state=DISABLED)
self.bottom_left_answer_button.config(state=DISABLED)
self.bottom_right_answer_button.config(state=DISABLED)
self.hint_button.config(state=DISABLED)
# Enable the next_button
self.next_button.config(state=NORMAL)
# Increase total rounds played by 1
self.played += 1
# Check if button is correct.
if location == self.answer:
self.answer_box.config(text="Correct!", fg="green")
self.score += 1
correct_answer = "{}, the answer was {} \u2713 \n".format(self.question,self.answer)
self.game_history.append(correct_answer)
else:
self.answer_box.config(text="Incorrect, correct country is {}".format(self.answer), fg="red")
incorrect_answer = "{}, the answer was {} \u274c, you answered \n".format(self.question,self.answer,location)
self.game_history.append(incorrect_answer)
# Update the score that the user has
self.score_label.config(text="{} correct / {} rounds played".format(self.score, self.played))
def to_next(self, capital_list, history):
# if the amount of rounds played is 15 the player is taken to the end screen
if self.played == 15:
easy=1
End(self.score, history,easy)
self.game_box.destroy()
# Else the quiz repeats and new questions are asked.
else:
self.top_left_answer_button.config(state=NORMAL)
self.top_right_answer_button.config(state=NORMAL)
self.bottom_left_answer_button.config(state=NORMAL)
self.bottom_right_answer_button.config(state=NORMAL)
self.next_button.config(state=DISABLED)
self.answer_box.config(text="")
self.hint_button.config(state=NORMAL)
# chooses four different countries / capitals from the list
question_ans = random.choice(capital_list)
yes = random.choice(capital_list)
no = random.choice(capital_list)
ok = random.choice(capital_list)
# Defining variables for the capitals and countries,
# question is the capital in question
# self.answer is the correct answer
# incorrect[1,2,3] are the incorrect countries.
self.question = question_ans[1]
self.answer = question_ans[0]
self.hint = question_ans[2]
incorrect1 = yes[0]
incorrect2 = no[0]
incorrect3 = ok[0]
self.capital_label.config(text=self.question)
# I made the button_list a list so the list can be randomized so that the answer button locations is always
# different.
button_list = [self.answer, incorrect1, incorrect2, incorrect3]
random.shuffle(button_list)
self.top_left = button_list[0]
self.top_right = button_list[1]
self.bottom_left = button_list[2]
self.bottom_right = button_list[3]
# Defining the randomized list to their corresponding buttons
self.top_left_answer_button.config(text=self.top_left, command=lambda: self.reveal_answer(self.top_left))
self.top_right_answer_button.config(text=self.top_right, command=lambda: self.reveal_answer(self.top_right))
self.bottom_left_answer_button.config(text=self.bottom_left,
command=lambda: self.reveal_answer(self.bottom_left))
self.bottom_right_answer_button.config(text=self.bottom_right,
command=lambda: self.reveal_answer(self.bottom_right))
def to_hint(self):
get_hint = Hint(self)
get_hint.help_text.configure(text="The country is located in: {}".format(self.hint))
class Hard:
def __init__(self):
# Background color is light yellow
background = "#FFF4C3"
# Game History List
self.game_history = []
# Import the csv file, name of csv file goes here...
with open('country-capitals.csv', 'r') as f:
# make csv file into list
file = csv.reader(f)
next(f)
my_list = list(file)
# choose an item from the main list, this item is itself a list
question_ans = random.choice(my_list)
# Initial Score
self.score = int(0)
# Amounts of games played
self.played = 0
# first item in small list
self.question = question_ans[1]
self.answer = question_ans[0]
self.hint = question_ans[2]
# GUI Setup
self.game_box = Toplevel()
self.game_frame = Frame(self.game_box, bg=background)
self.game_frame.grid()
self.game_box.protocol('WM_DELETE_WINDOW', to_quit)
# Capital Label row 0
self.capital_label = Label(self.game_frame, text=self.question,
font="Helvetica 15 bold", bg=background)
self.capital_label.grid(row=0, padx=5, pady=10)
# Setup Answer Entry row 1
self.answer_entry = Entry(self.game_frame, font="Helvetica 15 bold")
self.answer_entry.grid(row=1, pady=10, padx=30)
self.answer_entry.focus()
self.answer_entry.bind('<Return>', lambda e: self.check_answer())
# Button frame for "guess" and "next" row 2
self.button_frame = Frame(self.game_frame, bg=background)
self.button_frame.grid(row=2)
# Button to press when users have entered the country row 2.0 column 0
self.answer_button = Button(self.button_frame, text="Guess", font="Helvetica 10 bold",
command=lambda: self.check_answer())
self.answer_button.grid(row=0, column=0, padx=5)
# The hint button to get the hint for this country row 2 column 1
self.hint_button = Button(self.button_frame, text="Hint", command=self.to_hint, width=5,
font="Helvetica 10 bold")
self.hint_button.grid(row=0, column=1, padx=5)
# Button to go to the next question row 2.0 column 2
self.next_button = Button(self.button_frame, text="Next", font="Helvetica 10 bold",
command=lambda: self.next_question(my_list, self.game_history))
self.next_button.grid(row=0, column=2, padx=5)
self.next_button.config(state=DISABLED)
self.next_button.bind('<Return>', lambda e: self.next_question(my_list, self.game_history))
# Correct or incorrect Label row 3
self.answer_box = Label(self.game_frame, text="", font="Helvetica", bg=background, width=35, wrap=170)
self.answer_box.grid(row=3)
# Total amount of correct answers and games played row 4
self.points = Label(self.game_frame, text="{} correct / {} rounds played".format(self.score, self.played),
font="Helvetica 10", bg=background)
self.points.grid(row=4)
def check_answer(self):
user_answer = self.answer_entry.get()
self.hint_button.config(state=DISABLED)
self.played += 1
if user_answer.casefold() == self.answer.casefold():
self.answer_box.config(text="Correct!", fg="green")
self.score += 1
self.answer_entry.config(bg="#ACF392")
# History to be appended if correct
guess_history_correct = \
"{}, the answer was {} \u2705 \n".format(self.question,self.answer)
self.game_history.append(guess_history_correct)
else:
self.answer_box.config(text="The country is located in {}".format(self.answer), fg="#F62121")
self.answer_entry.config(bg="#F39292")
# History to be appended if incorrect
guess_history_incorrect = \
"{}, the answer was {} \u274c , you answered {} \n".format(self.question,self.answer,user_answer)
self.game_history.append(guess_history_incorrect)
self.next_button.config(state=NORMAL)
self.answer_button.config(state=DISABLED)
self.next_button.focus()
self.points.config(text="{} correct / {} rounds played".format(self.score, self.played))
def next_question(self, capital_list, guesses):
# When the user has played 15 rounds we take them to the end gui.
if self.played == 15:
hard=0
End(self.score, guesses,hard)
self.game_box.destroy()
# If they amount of played is not 15 new questions are generated.
else:
question_ans = random.choice(capital_list)
self.question = question_ans[1]
self.answer = question_ans[0]
self.hint = question_ans[2]
self.capital_label.config(text=self.question)
self.answer_entry.delete(0, "end")
self.answer_box.config(text="")
self.next_button.config(state=DISABLED)
self.answer_button.config(state=NORMAL)
self.answer_entry.config(bg="white")
self.answer_entry.focus()
self.hint_button.config(state=NORMAL)
def to_hint(self):
get_hint = Hint(self)
get_hint.help_text.configure(text="The country is located in: {}".format(self.hint))
if __name__ == "__main__":
root = Tk()
root.title("Country Quiz")
something = Start()
root.mainloop()

How to change colour for each sorting algorithms step in tkinter

This is my main code that creates a GUI. The user can enter the numbers or generate random numbers and it will sort it. However, i want it to change colour with each step taken in the sorting algorithm, and then change to a green colour once the array has been sorted.
import random
from tkinter import *
import Swap
numberArray = list()
def arrayList(number):
arrayListEntry.delete(0, END)
numberArray.append(number)
e.config(text=str(numberArray))
print numberArray
def randomiser():
for i in range(10):
numberArray.append(random.randint(1,100))
e.config(text=str(numberArray))
print numberArray
# Main selection sort function
def selectionSort(numberList):
for i in range(len(numberList)):
minimumIndex = i
print("\nMinimum index: " + str(minimumIndex))
for l in range(i + 1, len(numberList)):
if numberList[minimumIndex] > numberList[l]:
minimumIndex = l
print(numberArray)
Swap.startSwap(numberList, i, minimumIndex)
e.config(text=str(numberArray))
root.update()
root.after(1000)
e.config(text=str(numberArray))
width = 300
height = 250
root = Tk()
frame = Frame(root, width=width, height=height)
frame.grid(row=3, column=0, columnspan=3)
e = Label(root, text="Arraylist")
e.grid(row=1, column=1)
arrayListLabel = Label(root, text="Array List")
arrayListEntry = Entry(root)
arrayListButton = Button(root, text="Enter", command=lambda: arrayList(arrayListEntry.get()))
arrayListButton.grid(row=0, column=3)
sortButton = Button(root, text="Sort", command=lambda: selectionSort(numberArray))
sortButton.grid(row=2, column=1)
randomButton = Button(root, text="Randomise", command=lambda: randomiser())
randomButton.grid(row=3, column=1)
arrayListLabel.grid(row=0, column=0)
arrayListEntry.grid(row=0, column=1)
root.mainloop()
This is my swap method in another class, ignore the last line as that is only for the console for me to see what is happening
# Swap function for swaping the index in the array
def startSwap(array, firstIndex, secondIndex):
swapObject = array[firstIndex]
array[firstIndex] = array[secondIndex]
array[secondIndex] = swapObject
print("Number " + str(array[firstIndex]) + " swapped with number " + str(array[secondIndex]) + " in array\n")
I removed the frame widget as it was complicating the task of changing the color of the entire background.
I made the following changes inside the startSwap() function to change the colors at every step of the algorithm
First I created a list of color names:
colors = ['red', 'blue', 'orange', 'yellow']
Next, I randomly set the foreground color from the colors list. You can add other colors to increase randomness of color selection.
e.config(fg=random.choice(colors))
Finally when the the list of numbers are sorted, set the foreground color to green inside of the selectionSort() function
e.config(fg='green')
Here's the entire working code:
import random
from tkinter import *
#import Swap
root = Tk()
# define label before using it
e = Label(root, text="Arraylist")
e.grid(row=1, column=1, padx=10, pady=10)
numberArray = list()
def arrayList(number):
arrayListEntry.delete(0, END)
numberArray.append(number)
e.config(text=str(numberArray))
#print numberArray
def randomiser():
for i in range(10):
numberArray.append(random.randint(1,100))
e.config(text=str(numberArray))
#print numberArray
def startSwap(array, firstIndex, secondIndex):
# color list
colors = ['red', 'blue', 'orange']
# set a random color from the colors list
e.config(fg=random.choice(colors))
swapObject = array[firstIndex]
array[firstIndex] = array[secondIndex]
array[secondIndex] = swapObject
# Main selection sort function
def selectionSort(numberList):
for i in range(len(numberList)):
minimumIndex = i
for l in range(i + 1, len(numberList)):
if numberList[minimumIndex] > numberList[l]:
minimumIndex = l
#Swap.startSwap(numberList, i, minimumIndex)
startSwap(numberList, i, minimumIndex)
e.config(text=str(numberArray))
root.update()
root.after(1000)
e.config(text=str(numberArray))
# once numbers are sorted, set foreground as green
e.config(fg='green')
arrayListLabel = Label(root, text="Array List")
arrayListEntry = Entry(root)
arrayListButton = Button(root, text="Enter", command=lambda: arrayList(arrayListEntry.get()))
arrayListButton.grid(row=0, column=3, padx=10, pady=10)
sortButton = Button(root, text="Sort", command=lambda: selectionSort(numberArray))
sortButton.grid(row=2, column=1, pady=10)
randomButton = Button(root, text="Randomise", command=lambda: randomiser())
randomButton.grid(row=3, column=1, pady=10)
arrayListLabel.grid(row=0, column=0, padx=10, pady=10)
arrayListEntry.grid(row=0, column=1)
root.mainloop()
Lastly, I added some padding to the Label and Button widgets.

Tkinter Grid Alignment Issue

I'm pretty new with tkinter and I can't figure why the q is not aligned near the Entry.
# String
self.user_p = StringVar()
self.user_q = StringVar()
self.user_r = StringVar()
self.user_result = StringVar()
# Label
self.description = Label(self.root, text="!p v (q ^ r)")
self.pLabel = Label(self.root, text="p")
self.qLabel = Label(self.root, text="q")
self.rLabel = Label(self.root, text="r")
self.resultLabel = Label(self.root, text="Result")
# Entry
self.p = Entry(self.root, textvariable = self.user_p, width = 10)
self.q = Entry(self.root, textvariable = self.user_q, width = 10)
self.r = Entry(self.root, textvariable = self.user_r, width = 10)
self.result = Entry(self.root, bg = "white", state=DISABLED, text = "")
# Grid
# Labels
self.description.grid(row = 0, column = 3, sticky = N)
self.pLabel.grid(row = 1, column = 0, sticky = E)
self.qLabel.grid(row = 1, column = 2, sticky = E)
self.rLabel.grid(row = 1, column = 4, sticky = E)
# Entry
self.p.grid(row=1, column=1)
self.q.grid(row = 1, column = 3)
self.r.grid(row=1, column=5)
(with or without the sticky it's still the same)
Here's a picture: http://imgur.com/a/wrOGa
The first part in the picture is what I'm getting right now. And the second part is what I want it to look like
Am I doing something wrong?
Welcome. I have taken the liberty to attach an example of a test code (see below). Please remember to do that in your post as mine can be different to yours. I did not encounter the issue you described. See attached picture. I am using python3.5 on Ubuntu 16.04.
One other thing, you can be more explicit by adding the option justify=RIGHT in your label widget commands to alight the label text to right.
from tkinter import *
class App(Frame):
def __init__(self, parent):
Frame.__init__(self, parent, background='pink')
# String
self.user_p = StringVar()
self.user_q = StringVar()
self.user_r = StringVar()
self.user_result = StringVar()
# Label
self.description = Label(self, text="!p v (q ^ r)")
self.pLabel = Label(self, text="p")
self.qLabel = Label(self, text="q")
self.rLabel = Label(self, text="r")
self.resultLabel = Label(self, text="Result")
# Entry
self.p=Entry(self, textvariable=self.user_p, width=10)
self.q=Entry(self, textvariable=self.user_q, width=10)
self.r=Entry(self, textvariable=self.user_r, width=10)
self.result=Entry(self, bg="white", state=DISABLED, text="")
# Grid
# Labels
self.description.grid(row=0, column=3, sticky=N)
self.pLabel.grid(row=1, column=0, sticky=E)
self.qLabel.grid(row=1, column=2, sticky=E)
self.rLabel.grid(row=1, column=4, sticky=E)
# Entry
self.p.grid(row=1, column=1)
self.q.grid(row=1, column=3)
self.r.grid(row=1, column=5)
if __name__ == '__main__':
root=Tk()
root.geometry("300x50")
app=App(root)
app.pack(fill="both", expand=True)
app.mainloop()

Tkinter: Changing value of a Textbox after calculation to avoid duplicates

from tkinter import *
class HHRG:
def __init__(self, root):
self.root = root
self.RnReg = 50
self.RnResump = 80
self.RnCert = 80
self.RnDC = 70
self.RnSOC = 90
self.LvnReg = 40
self.LvnOut = 35
self.Hha = 25
self.Pt = 75
self.Ot = 75
self.St = 75
self.HHRGValue = IntVar()
self.RnRegValue = IntVar()
self.RnResumpValue = IntVar()
self.RnCertValue = IntVar()
self.RnDCValue = IntVar()
self.RnSOCValue = IntVar()
self.LvnRegValue = IntVar()
self.LvnOutValue = IntVar()
self.HhaValue = IntVar()
self.PtValue = IntVar()
self.OtValue = IntVar()
self.StValue = IntVar()
###LABELS###
self.HHRGLabel = Label(self.root, text="HHRG")
self.RnRegLabel = Label(self.root, text="Regular Rn Visits")
self.RnResumpLabel = Label(self.root, text="Rn Resumption Visits")
self.RnCertLabel = Label(self.root, text="Rn recertification Visits")
self.RnDCLabel = Label(self.root, text="Rn D/C Visits")
self.RnSOCLabel = Label(self.root, text="Rn SOC Visits")
self.LvnRegLabel = Label(self.root, text="Regular Lvn Visits")
self.LvnOutLabel = Label(self.root, text="Lvn Outlier Visits")
self.HhaLabel = Label(self.root, text="HHA visits")
self.PtLabel = Label(self.root, text="Pt Visits")
self.OtLabel = Label(self.root, text="Ot Visits")
self.StLabel = Label(self.root, text="St Visits")
self.TotalLabel = Label(self.root, text="Net Total")
###ENTRY BOXES###
self.HHRGEntry = Entry(self.root, textvariable=self.HHRGValue)
self.RnRegEntry = Entry(self.root, textvariable=self.RnRegValue)
self.RnResumpEntry = Entry(self.root, textvariable=self.RnResumpValue)
self.RnCertEntry = Entry(self.root, textvariable=self.RnCertValue)
self.RnDCEntry = Entry(self.root, textvariable=self.RnDCValue)
self.RnSOCEntry = Entry(self.root, textvariable=self.RnSOCValue)
self.LvnRegEntry = Entry(self.root, textvariable=self.LvnRegValue)
self.LvnOutEntry = Entry(self.root, textvariable=self.LvnOutValue)
self.HhaEntry = Entry(self.root, textvariable=self.HhaValue)
self.PtEntry = Entry(self.root, textvariable=self.PtValue)
self.OtEntry = Entry(self.root, textvariable=self.OtValue)
self.StEntry = Entry(self.root, textvariable=self.StValue)
self.TotalEntry = Text(root, height=2, width=10)
self.clearButton = Button(root, text="Clear")
self.clearButton.bind("<Button-1>", self.clear)
self.calculatebutton = Button(root, text="Calculate", width=10)
self.calculatebutton.bind("<Button-1>", self.clear)
self.calculatebutton.bind("<Button-1>", self.calculate)
####LABEL GRIDS###
self.HHRGLabel.grid(row=0, column=0)
self.RnRegLabel.grid(row=1, column=0)
self.RnResumpLabel.grid(row=2, column=0)
self.RnCertLabel.grid(row=3, column=0)
self.RnDCLabel.grid(row=4, column=0)
self.RnSOCLabel.grid(row=5, column=0)
self.LvnRegLabel.grid(row=6, column=0)
self.LvnOutLabel.grid(row=7, column=0)
self.HhaLabel.grid(row=8, column=0)
self.PtLabel.grid(row=9, column=0)
self.OtLabel.grid(row=10, column=0)
self.StLabel.grid(row=11, column=0)
self.TotalLabel.grid(row=12, column=0)
###ENTRY GRIDS###
self.HHRGEntry.grid(row=0, column=1)
self.RnRegEntry.grid(row=1, column=1)
self.RnResumpEntry.grid(row=2, column=1)
self.RnCertEntry.grid(row=3, column=1)
self.RnDCEntry.grid(row=4, column=1)
self.RnSOCEntry.grid(row=5, column=1)
self.LvnRegEntry.grid(row=6, column=1)
self.LvnOutEntry.grid(row=7, column=1)
self.HhaEntry.grid(row=8, column=1)
self.PtEntry.grid(row=9, column=1)
self.OtEntry.grid(row=10, column=1)
self.StEntry.grid(row=11, column=1)
self.TotalEntry.grid(row=12, column=1)
self.calculatebutton.grid(columnspan=2, pady=10)
self.clearButton.grid(row=13, column=1)
def calculate(self, event):
values = [(self.RnRegValue.get() * self.RnReg),
(self.RnResumpValue.get() * self.RnResump),
(self.RnCertValue.get() * self.RnCert),
(self.RnDCValue.get() * self.RnDC),
(self.RnSOCValue.get() * self.RnSOC),
(self.LvnRegValue.get() * self.LvnReg),
(self.LvnOutValue.get() * self.LvnOut),
(self.HhaValue.get() * self.Hha),
(self.PtValue.get() * self.Pt),
(self.OtValue.get() * self.Ot),
(self.StValue.get() * self.St)]
self.total = 0
for i in values:
self.total += i
result = self.HHRGValue.get() - self.total
self.TotalEntry.insert(END, result)
def clear(self, event):
self.TotalEntry.delete("1.0", END)
root = Tk()
a = HHRG(root)
root.mainloop()
So i've got this modified calculator of mine and the problem with it is everytime you calculate. it returns outputs as desired but if you click it twice
it'll duplicate
I tried binding the self.calculatebutton to my clear() method but it wouldn't prevent the duplication of the results
my question is. How can we make it calculate the desired output but wipe the previous output at the same time to prevent duplicates? so if someone presses the calculate button multiple times it'll only output one total not multiple ones like the picture above
This code is where the problem lies:
self.calculatebutton = Button(root,text="Calculate",width=10)
self.calculatebutton.bind("<Button-1>",self.clear)
self.calculatebutton.bind("<Button-1>",self.calculate)
When you call bind, it will replace any previous binding of the same event to the same widget. So, the binding to self.clear goes away when you add the binding to self.calculate. While there are ways to bind multiple functions to an event, usually that is completely unnecessary and leads to difficult-to-maintain code.
The simple solution is for your calculate function to call the clear function before adding a new result:
def calculate(self,event):
...
result = self.HHRGValue.get() - self.total
self.clear(event=None)
self.TotalEntry.insert(END,result)
Note: if this is the only time you'll call clear, you can remove the event parameter from the function definition, and remove it from the call.
On a related note: generally speaking you should not use bind on buttons. The button has built-in bindings that normally work better than your custom binding (they handle keyboard traversal and button highlighting, for example).
The button widget has a command attribute which you normally use instead of a binding. In your case it would look like this:
self.calculatebutton = Button(..., command=self.calculate)
When you do that, your calculate method no longer needs the event parameter, so you'll need to remove it. If you want to use the calculate function both from a command and from a binding, you can make the event optional:
def calculate(self, event=None)
A simple fix could be to just call your clear method in your calculate method, before inserting the text into your TotalEntry text widget.
Try this:
def calculate(self,event):
values = [(self.RnRegValue.get() * self.RnReg),
(self.RnResumpValue.get() * self.RnResump),
(self.RnCertValue.get() * self.RnCert),
(self.RnDCValue.get() * self.RnDC),
(self.RnSOCValue.get() * self.RnSOC),
(self.LvnRegValue.get() * self.LvnReg),
(self.LvnOutValue.get() * self.LvnOut),
(self.HhaValue.get() * self.Hha),
(self.PtValue.get() * self.Pt),
(self.OtValue.get() * self.Ot),
(self.StValue.get() * self.St)]
self.total = 0
for i in values:
self.total += i
result = self.HHRGValue.get() - self.total
self.clear(event)
self.TotalEntry.insert(END,result)

Categories

Resources