How can I make a grading button from tkinter entry? - python-3.x

I was making a program for vocab test, and I needed to make each Entries to type in the answer. However, I found it out making every single Entries is very inefficient so I used for i in range(0,35) to make Entries. But now I am stuck with getting the value of each Entries. How can I make a button to collect all the .get() from each Entries that doesn't have names?
import tkinter
from tkinter import *
window = tkinter.Tk()
container = tkinter.Frame(window)
canvas = tkinter.Canvas(container)
window.title('Rescue word test')
window.geometry('640x480')
window.resizable(True, True)
scrollbar = tkinter.Scrollbar(container, orient="vertical", command=canvas.yview)
#scroll
main_frame = Frame(window)
main_frame.pack(fill=BOTH, expand=1)
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_scrollbar = tkinter.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_scrollbar.bind('<Configure>', lambda e: my_canvas.configure(scrollregion= my_canvas.bbox("all")))
second_frame = Frame(my_canvas)
my_canvas.create_window((0,0), window= second_frame, anchor="nw")
def mouse_scroll(event):
my_canvas.yview_scroll(-1 * int((event.delta / 120)), "units")
my_canvas.bind_all("<MouseWheel>", mouse_scroll)
def getEntry( i ):
return list( second_frame.children.values() )[ i ]
Day21_eng = ['exquisite', 'acquisition', 'regulate', 'transportation', 'insight', 'straightforward', 'cultivate', 'innovation', 'preserve', 'odor', 'exception', 'munch', 'proclaim', 'slap', 'variability', 'investigate', 'flare', 'outpace', 'genuine', 'plead', 'fossilize', 'toil', 'drastic', 'withhold', 'inanimate', 'clockwise', 'amnesia', 'revive', 'theorize', 'culprit', 'limp', 'worn-out', 'indignity', 'span', 'bribe']
Day21_kor = [['우아한', '정교한', '절묘한'], ['취득', '획득', '습득'], ['규제하다', '통제하다'], ['운송', '운임', '추방'], ['통찰', '통찰력'], ['명확한', '솔직한'], ['경작하다', '기르다', '장려하다', '육성하다'], ['혁신'], ['보전', '보호지', '보호하다', '보존하다'], ['냄새', '악취', '기미', '낌새'], ['예외'], ['우적우적 먹다'], ['선언하다'], ['찰싹 때리다'], ['변화성', '가변성', '변용성'], ['조사하다'], ['불끈 성나게 하다', '이글거리다', '불꽃', '타오름'], ['앞지르다', '속도가 더 빠르다'], ['진짜의', '진품의'], ['탄원하다', '변호하다', '애원하다'], ['고착화하다', '화석화하다'], ['수고', '노고', '힘들게 일하다'], ['급격한', '극단적인'], ['보류하다', '유보하다'], ['생명 없는', '무생물의'], ['시계방향으로'], ['기억상실'], ['부활시키다', '되살아나게 하다'], ['이론화하다'], ['죄인', '범죄자', '장본인'], ['절뚝거리다', '느릿느릿 가다', '기운이 없는','축 처진'], ['닳아빠진', '진부한', '지친'], ['모욕', '무례', '치욕'], ['기간', '폭', '범위', '걸치다', '이르다'], ['뇌물을 주다', '뇌물']]
b = 0
for i in range(0,35):
lable = Label(second_frame, text= Day21_eng[b])
lable.grid(column=0, row=b)
#입력 값 35개
entry = tkinter.Entry(second_frame, width=30)
entry.grid(row=b, column=1, sticky='nsew')
# important to bind each one for access
entry.bind('<Return>', getEntry)
b += 1
b_check = Button(second_frame, text='grade')
b_check.grid(columnspan=2, row=36)
window.mainloop()
I want to make if I press the 'grade' button, that sends a command to check if the .get() of the each Entries are in the Day21_kor list.

You can use a list to store the Entry widgets and use this list inside the callback of grade.
...
def check():
for i, e in enumerate(entries):
value = e.get()
print(value, value in Day21_kor[i])
# or whatever you want to do
entries = []
for row, item in enumerate(Day21_eng):
lable = tkinter.Label(second_frame, text=item)
lable.grid(column=0, row=row)
#입력 값 35개
entry = tkinter.Entry(second_frame, width=30)
entry.grid(row=row, column=1, sticky='nsew')
# important to bind each one for access
entry.bind('<Return>', getEntry)
entries.append(entry) # save 'entry' into list
b_check = tkinter.Button(second_frame, text='grade', command=check)
b_check.grid(columnspan=2, row=36)
Note that there are other issues in your code:
unused widgets: container, canvas and scrollbar
should bind <Configure> on second_frame instead of my_scrollbar
exception when getEntry() is executed. What do you want to do inside this function actually?

A slight change to #acw1668 code will output results to shell and produce a dictionary of results - called result
result = dict()
def check():
global result
for i, e in enumerate(entries):
name = description[ i ][ 'text' ]
value = e.get()
print( name, value )
result[ name ] = value
entries = []
description = []
for row, item in enumerate(Day21_eng):
lable = tkinter.Label(second_frame, text=item)
lable.grid(column=0, row=row)
#입력 값 35개
entry = tkinter.Entry(second_frame, width=30)
entry.grid(row=row, column=1, sticky='nsew')
description.append( lable )
entries.append(entry)
b_check = tkinter.Button(second_frame, text='grade', command=check)
b_check.grid(columnspan=2, row=36)

Related

What can i do to print information from a nested dictionary that is send to class, and i need to show the result on the GUI

I am very stuck by trying to use tkinter, right now I am trying to print a receipt, my code works without the GUI, it prints the receipt sending the necessary information to a class, but now the professor wants us to have a GUI.
This is a one of the classes that I am using:
class Combo:
def __init__(self, dish, drink, order, price):
self.dish = dish
self.drink = drink
self.order = order
self.price = price
def combo_receipt(self, combo_number):
"""
This is for printing on the receipt the information of the combo
:return:
"""
return f"Combo {combo_number}.\nDish {self.dish}.\nDrink Order {self.drink}.\nFood Order {self.order}.\n" \
f"Price {self.price}.\n -------------"
This is how I am recollecting the information from a nested dictionary to send it to another function:
def receipt_print(customer_receipts, taxes):
"""
This function will start the process of printing the receipt of the customer
:param customer_receipts: receipts dictionary
:param taxes: the tax to the math operation
:return:
"""
for key, value in customer_receipts.items():
print(key)
customer_name = input("Which receipt do you want to print?")
if customer_name in customer_receipts:
loop_print = int(customer_receipts[customer_name]["n_orders"])
num_of_orders = 0
total = 0
for n in range(loop_print):
if f"id{num_of_orders}" in customer_receipts[customer_name]:
if "fries" in customer_receipts[customer_name][f"id{num_of_orders}"]:
fr = "fries"
order_type = "food"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"]["fries"]["price"])
total += cost
order_print(fr, customer_receipts, order_type, customer_name, id_num_of_orders)
num_of_orders += 1
elif "soda" in customer_receipts[customer_name][f"id{num_of_orders}"]:
sd = "soda"
order_type = "drink"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"][sd]["price"])
total += cost
order_print(sd, customer_receipts, order_type, customer_name, id_num_of_orders)
num_of_orders += 1
elif "combo_1" in customer_receipts[customer_name][f"id{num_of_orders}"]:
cb1 = "combo_1"
combo_num = "1"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"][cb1]["price"])
total += cost
combo_print(cb1, customer_receipts, combo_num, customer_name, id_num_of_orders)
num_of_orders += 1
elif "combo_2" in customer_receipts[customer_name][f"id{num_of_orders}"]:
cb2 = "combo_2"
combo_num = "2"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"][cb2]["price"])
total += cost
combo_print(cb2, customer_receipts, combo_num, customer_name, id_num_of_orders)
num_of_orders += 1
elif "pizza" in customer_receipts[customer_name][f"id{num_of_orders}"]:
pz = "pizza"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"][pz]["price"])
total += cost
dish_print(pz, customer_receipts, customer_name, id_num_of_orders)
num_of_orders += 1
else:
sp = "spaghetti"
id_num_of_orders = f"id{num_of_orders}"
cost = int(customer_receipts[customer_name][f"id{num_of_orders}"][sp]["price"])
total += cost
dish_print(sp, customer_receipts, customer_name, id_num_of_orders)
num_of_orders += 1
total_print(total, taxes)
else:
print("Wrong receipt.\nBack to the menu")
In this case, the function that will handle the combos that the customer order, is:
def combo_print(combo, customer_receipts, comb_num, customer_name, id_or):
"""
When this function is call, it will print the combo information
:param combo: a variable to know which combo is in the order
:param customer_receipts: receipts dictionary
:param comb_num: a variable to be sent to the class Order
:param customer_name: a variable with the name of the customer to read the receipt dictionary
:param id_or: a variable with the name of the customer to read the receipt dictionary
:return:
"""
combo_order = customer_receipts[customer_name][id_or][combo]["order"]
combo_price = customer_receipts[customer_name][id_or][combo]["price"]
combo_drink = customer_receipts[customer_name][id_or][combo]["drink"]
combo_dish = customer_receipts[customer_name][id_or][combo]["dish"]
fill_object = Combo(combo_dish, combo_drink,combo_order, combo_price)
print(fill_object.combo_receipt(comb_num))
And this will be calling the function def combo_receipt on the class class Combo:, so with this class and another three, one for Dishes, other one for Orders and the last one for the total, it will be printing the receipt for the customer.
This is what it prints:
Just for visualize, the nested directory looks like this:
receipts = {"jONH": {"n_orders": 1,
"id0": {"combo_2": {"dish": "Spaghetti Carbonara",
"drink": "Soda",
"order": "French Fries",
"price": "10", "id": "combo"}}},
"Josh": {"n_orders": 2,
"id0": {"combo_1": {"dish": "Personal Pizza",
"drink": "Soda",
"order": "French Fries",
"price": "8",
"id": "combo"}},
"id1": {"soda": {"order": "Soda",
"price": "2",
"id": "order"}
}
}
}
But as I already said, I need to use a GUI, but I know if there is a way to save the return value from the function def combo_receipt on the class class Combo: and send it to the GUI or what I can do to still be using the class and the GUI, cause it is requested.
I can't show you anything about my tries with this, cause I am really stuck with the GUI, so I am just watching video guides of tkinter or looking in google for information.
I will appreciate any advice, link or anything that help me to understand what I need to do
I have here an oop solution for the GUI where you can implement your functions. In the main file you create the app, mainFrame and Notebook with a tab.
In the second File you get the class with the init function for Entries/Labels/Buttons, you have to add elements you need. On the bottom you are able to implement your functions. Hope that helps you further with the GUI.
main.py:
import tkinter as tk
from tkinter import ttk
from abc import createUI0
# class MainFrame that inherits from ttk.Frame
class MainFrame(ttk.Frame): #ttk.Frame
def __init__(self, container): #init method
super().__init__(container)
# Create notebook
self.tabControl = ttk.Notebook(self)
tab1 = createUI0(self.tabControl)
# Create Tab from tab1 from file XYZ
self.tabControl.add(tab1, text ='XYZ')
self.tabControl.pack(expand = 1, fill ="both")
if __name__ == "__main__":
app = tk.Tk()
app.title('XZY')
app.geometry('670x580')
app.resizable(0, 0)
MainFrame(app).pack(side="top", fill="both", expand=True)
app.mainloop()
abc.py:
import tkinter as tk
from tkinter import ttk
from tkinter import *
class createUI0(ttk.Frame):
def __init__(self, container): #init method
super().__init__(container)
# field options
options = {'padx': 5, 'pady': 5}
# Titel Labels
self.title = ttk.Label(self, text='XXX', font=('Helvetica', 17, 'bold'))
self.title.grid(column=1, row=0, sticky=tk.W, **options)
# Item Detail Labels
self.itemDetail = ttk.Label(self, text='YYY:', font=('Helvetica', 16, 'bold'))
self.itemDetail.grid(column=0, row=5, sticky=tk.W, **options)
# XEntry, your variable to work with
self.X = tk.StringVar()
self.XEntry = ttk.Entry(self, width=23, textvariable=self.X)
self.XEntry.grid(column=1, row=11, sticky=tk.W, **options)
self.XEntry.focus()
# Button to start your function for example
self.button_create = ttk.Button(self, width = 15, text='use YourFunction', command=self.yourFunction)
self.button_create.grid(column=0, row=22, **options, sticky=tk.W)
def yourFunction(self):
#your function
pass

How do I make sure all GUI input variables can be accessed by certain classes and function calls?

When I provide an address /and or location to the entry bar and I press the "Get forecast" button the script fails at line 22. I think the error is raised because the str(address.get()) cant find the address variable, probably because it doesn't technically exist during that point of run time (I'm not able to log the error due to the structure of that function).
My question is; How do I make sure that my "get_hourly_forecast" function is able to access the address entry variable?
I have tried instantiating the address variable in various locations, e.g in the MainWeatherHub class, as well as in the MyWeatherApp class and then passing it as an argument to the MainWeatherHub in line 79, neither variation has worked. The current code shows the former variation.
import urllib, json, requests
from tkinter import *
from tkinter import ttk
def get_hourly_forecast(*args):
## params *args:
#A location argument
#Returns:
# A list of temps in Farenheit for the next 156 hours
API_KEY = 'removing my API key for security purposes'
try:
print('here') # The code makes it to here
curr_address = str(address.get()) # Code seems to fail here (not sure how to have the error print)
print('here')
geocode_url = "https://maps.googleapis.com/maps/api/geocode/json?address={}&key={}".format(cur_address, API_KEY)
response = requests.get(geocode_url)
response_dict = response.json()['results']
location = response_dict[0]['geometry']['location']
lat = location['lat']
lng = location['lng']
local_url_request = 'https://api.weather.gov/points/lat={}lng={}'.format(lat, lng)
response_one = requests.get(local_url_request)
json_dict_one = response_one.json()
local_props = json_dict_one['properties']
local_forecast_request = local_props['forecastHourly']
resposne_two = requests.get(local_forecast_request)
json_dict_two = resposne_two.json()
local_forecast_properites = json_dict_two['properties']
hourly_updates = local_forecast_properites['periods']
out = []
for i in hourly_updates:
for key, value in i.items():
if key == "temperature":
out.append(value)
current_weather.set(out[0])
except:
print("Not working.")
#############################################################
class MyWeatherApp:
"""
MyWeatherApp is the primary Frame for this GUI application
"""
def __init__(self, master):
super(MyWeatherApp, self).__init__()
self.master = master
# Create the main window Frame
master_style = ttk.Style()
master_style.configure('Master.TFrame')
self.master.title("My Weather")
self.master.geometry("500x500")
MWA = ttk.Frame(self.master, style='Master.TFrame')
MWA.place(relheight=1.0, relwidth=1.0)
# Run other widgets within this class
MainWeatherHub(MWA)
#############################################################
class MainWeatherHub(MyWeatherApp):
"""
The MainWeatherHub (MWH) is the top panel of the app
"""
def __init__(self, mainwindow):
super(MyWeatherApp, self).__init__()
self.mainwindow = mainwindow
# Create a Frame for the MainWeatherHub
MWH_style = ttk.Style()
MWH_style.configure('MWH.TFrame')
MWH = ttk.Frame(self.mainwindow, style='MWH.TFrame', relief='sunken')
MWH.place(relheight=0.33, relwidth=0.95, relx=0.025, rely=0.025)
# Create an entry widget to take a location
# and store that as a loction variable.
address = StringVar()
loc_entry = ttk.Entry(MWH, textvariable=address)
loc_entry.place(relheight=0.30, relwidth=.95, relx=0.025, rely=0.05)
# Get weather button finds weather for the users location
current_weather = StringVar()
get_weather_button = ttk.Button(loc_entry, text="Get Forecast", command=get_hourly_forecast)
get_weather_button.place(relheight=0.85,relwidth=0.2, relx=0.79, rely=0.075)
#Display weather in the Message widget
weath_display = Message(MWH, textvariable=current_weather)
weath_display.place(relwidth=0.95, relheight=0.55, relx=0.025, rely=0.375)
root = Tk()
my_gui = MyWeatherApp(root)
root.mainloop()
If this script works properly, it should return the current temperature in degrees Fahrenheit of the location that was provided in the entry bar.
You should send it as parameter
def get_hourly_forecast(cur_address):
geocode_url = "...".format(cur_address, API_KEY)
And then assing to button function which runs get_hourly_forecast with string
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
self.address = StringVar() # use self.
ttk.Button(loc_entry, text="Get Forecast", command=run_it)
def run_it(self):
get_hourly_forecast(self.address.get())
or using lambda
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
ttk.Button(loc_entry, text="Get Forecast", command=lambda:get_hourly_forecast(address.get()))
EDIT:
I see you use current_weather (StringVar from MainWeatherHub) in get_hourly_forecast to set value current_weather.set(out[0]).
You could send current_weather to get_hourly_forecast as parameter
def get_hourly_forecast(cur_address, current_weather):
geocode_url = "...".format(cur_address, API_KEY)
current_weather.set(out[0])
and
class MainWeatherHub(MyWeatherApp):
def __init__(self, mainwindow):
self.address = StringVar() # use self.
self.current_weather = StringVar() # use self.
ttk.Button(loc_entry, text="Get Forecast", command=run_it)
def run_it(self):
get_hourly_forecast(self.address.get(), self.current_weather)
but it could be better to return value from get_hourly_forecast
def get_hourly_forecast(cur_address):
geocode_url = "...".format(cur_address, API_KEY)
return out[0]
and get it in run_it
def run_it(self):
result = get_hourly_forecast(self.address.get())
if result is not None:
self.current_weather.set(result)
This way get_hourly_forecast doesn't work with StringVar and you can use it in other program which doesn't use StringVar.

Unable to bind function after pickling - tkinter

I have simple code which creates two fields by the press of a button. There are two other buttons to save and load back the entry fields created. I have used the bind function to bind field A and field B. Pressing the Enter button on field A after entering a number will print out its value multiplied by 5 in field B. At this point the bind function works perfectly.
When I create three entry fields and save the progress without entering any inputs and compile the program, then load the file, the bind function does not seem to work. It seems to work only for the last field created. My code is as follows. I tried my best to simplify the code.
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfile
from tkinter import messagebox
import pickle
class Test(Frame):
def Widgets(self):
self.button_add = Button(self, text = "Add", command = self.add)
self.button_add.grid(row=0, column =2)
self.button_save = Button(self, text = "save", command = self.save)
self.button_save.grid(row=0, column =3)
self.button_load = Button(self, text = "load", command = self.load)
self.button_load.grid(row=0, column =4)
def add(self):
def test(event):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
self.field_A.append({})
n = len(self.field_A)-1
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
n = len(self.field_B)-1
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
def save(self):
for n in range(len(self.field_A)):
self.entry_A.append(self.field_A[n].get())
self.entry_B.append(self.field_B[n].get())
fname = asksaveasfile(mode = "w", defaultextension = ".est")
data = {"fields": len(self.field_A), "entries_A": (self.entry_A),"entries_B": (self.entry_B)}
with open(fname.name, "wb") as file:
pickle.dump(data, file)
def load(self):
def test(event):
print("Why is the value of n always equal to", n, "?")
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
fname = askopenfilename(filetypes = (("Estimation Files (est)", "*.est"),))
location = fname.replace("/", "\\")
if location:
with open(location, "rb") as file:
data = pickle.load(file)
for n in range(data["fields"]):
self.field_A.append({})
self.field_A[n] = Entry(self)
self.field_A[n].grid(row=n, column =0)
self.field_A[n].insert(0, data["entries_A"][n])
self.field_A[n].bind("<Return>", test)
self.field_B.append({})
self.field_B[n] = Entry(self)
self.field_B[n].grid(row=n, column =1)
self.field_B[n].insert(0, data["entries_B"][n])
def __init__(self,master = None):
Frame.__init__(self, master)
self.field_A = []
self.field_B = []
self.entry_A = []
self.entry_B = []
self.grid()
self.Widgets()
root = Tk()
app = Test(master = None)
app.mainloop()
You need a "closure". You can make a closure in python with the functools.partial function.
from functools import partial
def test(n, event=None):
self.field_B[n].delete(0, END)
self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)
#other code ...
self.field_A[n].bind("<Return>", partial(test, n))
Both of your test() functions are accessing a variable n from the enclosing function. In the case of add(), there is no loop; n has a single value. Each Entry's test() gets its own n, because they were bound by a distinct call to add(). In load(), however, you are looping over n values; each test() is referring to the same n, which will have its final value by the time that any binding can possibly be invoked. The other answer gives a reasonable way to give each instance of test() its own personal n, so I'm not going to repeat that here.

How to store in variables current row selection within tree widget to query a database using python

I wonder if it is possible to store in variables the contents from a tree widget row (when it is selected with the mouse) see picture. Basically I want to sync my tree with a database, every time when I insert or delete an element in my tree, my database needs to auto update.
With the insert part it is not a problem , because I have entry widgets, but I don't know how to manage the delete part. Therefore, I wonder if it is possible to do this with some cursor selection function.
I have been trying for a very long time to find a solution for this, I would really appreciate if someone can help me with some hints
Code:
import tkinter
from tkinter import ttk
class cards(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
self.parent=parent
self.parent.geometry("800x500")
self.initialize_user_interface()
def initialize_user_interface(self):
self.parent.title("cards")
self.parent.grid_rowconfigure(0,weight=1)
self.parent.grid_columnconfigure(0,weight=1)
self.parent.config(background="lavender")
self.Card_label = tkinter.Label(self.parent, text = "Card type:")
self.Card_entry = tkinter.Entry(self.parent)
self.Card_label.place(x=5,y=5)
self.Card_entry.place(x=70,y=5)
self.SN_label = tkinter.Label(self.parent, text = "SN:")
self.SN_entry = tkinter.Entry(self.parent)
self.SN_label.place(x=5,y=40)
self.SN_entry.place(x=70,y=40)
self.submit_button = tkinter.Button(self.parent, text = "Insert", command = self.insert_data)
self.submit_button.place(x=210,y=15)
self.exit_button = tkinter.Button(self.parent, text = "Exit", command = self.exit)
self.exit_button.place(x=270,y=15)
self.tree = ttk.Treeview( self.parent, columns=('Card Type', 'SN'))
self.tree.heading('#0', text='Nr.')
self.tree.heading('#1', text='Card Type')
self.tree.heading('#2', text='SN')
self.tree.column('#1', stretch=tkinter.YES)
self.tree.column('#2', stretch=tkinter.YES)
self.tree.column('#0', stretch=tkinter.YES)
self.tree.place(x=0,y=100)
self.treeview = self.tree
self.i = 1
def exit(self):
self.master.destroy()
def insert_data(self):
self.treeview.insert('', 'end', text=str(self.i), values=(self.Card_entry.get(), self.SN_entry.get()))
self.i = self.i + 1
def main():
root=tkinter.Tk()
d=cards(root)
root.mainloop()
if __name__=="__main__":
main()
You can use
for item in self.tree.selection():
print(self.tree.item(item, "text"))
print(self.tree.item(item, "values"))
#print(self.tree.item(item))
to see data from all selected rows - you can select more than one row.
You can use it in function assigned to button
or you can use bind() to assign function to mouse click on row.

Creating tkinter gui.How to display information when ID number provided

I am working on creating a gui and could use some help. There are three programs that build off of each other. MY imput will be two CSV files, Examples below:
items4.csv
12345,Italy,100
13579,China,50
ETC.
transactions4.csv
12345,15
13579,10
12345,20
13579,-10
What I want it to do is upon running the gui will open and the window will ask for the "Item ID" Upon entering an id, say 12345, it will open up a new window that displays the following: getID, getName, getAvailableStart, and getAvailableEnd, all of these definitions are were created by the travelclass program (found below) when the program travelToolbox reads the two CSV files.
Note: Both the travelClass and travelToolbox programs are working fine. IT is only travelSystem that needs changing at this point
What I've done:
At this point I have managed to get the travelSystems presents the initial GUI however it doesn't matter what I enter in the entry box because when I hit the open button the next gui opens up but it only shows the information found in the first line of items4.csv. I think my main issue is line 34 or may be line 16. Let me know if any other information is needed.
I could really appreciate some help. Thank you in advance.
travelsystem
from travelToolbox import readItems, readTransactions
from tkinter import *
from tkinter import font
import tkinter as tk
class myApp :
def __init__(self, top, itemRecords) :
self.root = top
# Create a container Frame at the bottom
self.bframe = Frame(self.root)
self.bframe.pack(side=BOTTOM) # Create Label
self.xlabel = Label(self.root, text="Item ID")
self.xlabel.pack(side=LEFT)
self.xentry = Entry(self.root, bd=5) # Create Entry box
self.xentry.pack(side=LEFT)
self.xentry.focus_set() # Set focus in Entry box
self.xopen = Button(self.root, text="Open", command=self.showStockItem) # Create open Button
self.xopen.pack(side=LEFT)
self.xquit = Button(self.bframe, text="Quit", command=self.quitit ) # Create quit Button
#self.root instead of bframe
self.xquit.pack(side=BOTTOM)
def showStockItem(self):
tbl = Toplevel() # Create Toplevel window
hdr = font.Font(underline=1, weight="bold") # Create header font
tid = Label(tbl, text="ID", font=hdr) # Create 4 column headers in grid
tid.grid(row=0, column=0)
tlast = Label(tbl, text="Name", font=hdr)
tlast.grid(row=1, column=0)
tfirst = Label(tbl, text="Start", font=hdr)
tfirst.grid(row=2, column=0)
tlabel = Label(tbl, text="End", font=hdr)
tlabel.grid(row=3, column=0)
for rec in itemRecords.values() :
tid = Label(tbl, text= rec.getID()) # Create 4 column headers in grid
tid.grid(row=0, column=1)
tlast = Label(tbl, text= rec.getName())
tlast.grid(row=1, column=1)
tfirst = Label(tbl, text= rec.getAvailableStart())
tfirst.grid(row=2, column=1)
tlabel = Label(tbl, text= rec.getAvailableEnd())
tlabel.grid(row=3, column=1)
#self.xquit.pack(side=BOTTOM) #May not need this.
return
def quitit(self):
self.root.destroy()
return
itemsFileName = "items4.csv"
transactionsFileName = "transactions4.csv"
# itemRecords is a dictionary of stockItem records indexed by item ID
itemRecords = {}
# Read the items from itemsFileName into itemRecords
readItems(itemsFileName, itemRecords)
# Read the transactions from transactionsFileName into itemRecords
readTransactions(transactionsFileName, itemRecords)
top = tk.Tk()
#top = Travel()
app = myApp(top, itemRecords)
top.mainloop()
Other files:
travelToolbox
import csv
from travelClass import travelItem
def readItems(itemsFileName, itemRecords) :
# readItems reads items from itemsFileName into the itemRecords dictionary
# Open itemsFileName and create a CSV file reader
itemsFile = open(itemsFileName, 'r')
itemsReader = csv.reader(itemsFile)
# Process each row of the items file
for row in itemsReader :
# Get the values for the record
(iid, iname, icount) = row
iid = str(iid)
iname = str(iname)
icount = int(icount)
# Check if this ID is not yet in itemRecords
if (not(iid in itemRecords)) :
# Create a travelItem object and add it to itemRecords
itemRecord = travelItem(iid, iname, icount)
itemRecords[iid] = itemRecord
def readTransactions(transactionsFileName, itemRecords) :
# readTransactions reads transactions from transactionsFileName into the itemRecords dictionary
transactionFile = open(transactionsFileName, 'r')
transactionReader = csv.reader(transactionFile)
for row in transactionReader :
# Get the values for the record
(iid, itransaction) = row
iid = str(iid)
itransaction = int(itransaction)
itemRecords[iid].appendTransaction(itransaction)
#for key, value in itemRecords.items() :
transactionFile.close()
travelClass
class travelItem :
Class travelItem :
def __init__(self, itemID, itemName, itemCount) :
# Constructor to create inventoryItem CORRECT
self.id = itemID
self.name = itemName
self.AvailableStart = itemCount
self.transactions = []
def getID(self) :
# getID returns the tour ID CORRECT
return(self.id)
def getName(self) :
# getName returns the tour name CORRECT
return (self.name)
def setName(self, newName) :
# setName sets the tour name
self.name = newName
def getAvailableStart(self) :
# returns the starting availability
return (self.AvailableStart)
def appendTransaction(self, num) :
# appendTransaction appends a transaction to the transactions list
self.transactions.append(num)
def getTransactions(self) :
# getTransactions returns the list of transactions
return (self.transactions)
def getReservations(self) :
# returns the total of reservation transactions
total = 0
for num in self.transactions :
if ((num) > 0):
total += (num)
self.Reservations = total
return(self.Reservations)
def getCancellations(self) :
# returns the total of cancellation transactions
total = 0
for num in self.transactions :
if (num <= 0):
total += (num)
return(total)
def getAvailableEnd(self) :
# returns the ending availability, which is availableStart minus transactions
self.AvailableEnd = ((self.AvailableStart) - (self.Reservations) - (self.getCancellations()))
return(self.AvailableEnd)

Resources