Why do i need to use this user = dict() - python

from tkinter import *
main_window = Tk()
main_window.title("Register now")
frame = Frame(main_window)
frame.pack()
l_name = Label (frame, text = "Name:")
#metodo entende que é a mesma coisa que l_name.grid(row = 0, column = 0)
l_name.grid()
e_name = Entry(frame)
e_name.grid(row = 0, column =1)
l_lastname = Label(frame, text = "Last name:")
#metodo entende que é a mesma coisa que l_name.grid(row = 1, column = 0)
l_lastname.grid(row = 1)
e_lastname = Entry(frame)
e_lastname.grid(row = 1, column =1)
l_email = Label (frame, text = "E-mail:")
l_email.grid(row = 2)
e_email = Entry(frame)
e_email.grid(row = 2, column =1)
def convert_to_dict():
user = dict()
user['name'], user['last_name'], user['e-mail'] = e_name.get(), e_lastname.get(), e_email.get()
print(user)
Button(frame, text = "Send", command = convert_to_dict).grid(row=3,column =1)
Why i need this comanda user = dict()? I am telling the programn that the variable user is a dict() and thats ok, but i want to know if put user = {} would do same harm to the code

The statement user = dict() creates a new and empty python dictionary which you then fill with content on the subsequent line.
The approach looks rather non-pythonic to me. I would rather initialize and fill the dictionary in one go as TheLizzard suggested:
user = {"name": e_name.get(), "last__name": e_lastname.get(), ...}
You can achieve the same thing with the dict() method but it may result in more visual clutter in this case. However, the dict() method comes with a bunch of other handy ways to create and fill dictionaries in programmatic ways. e.g. this resource gives a nice overview: https://www.programiz.com/python-programming/dictionary

Related

Tkinter delete not working on referenced entry when referenceing lenth of entry

I have a tkinter window class that I've made and my delete function is not working properly.
my_window = tk.Tk()
class QuoteForm():
def __init__(self,master):
self.file_data = ''
self.master = master
self.master.rowconfigure(0, weight=1)
self.master.rowconfigure(1, weight= 1)
self.master.rowconfigure(2, weight = 1)
master.geometry('600x400')
master.resizable(False,False)
#create the frames
self.directory_frm = tk.Frame(master=master)
self.directory_frm.grid(row=0) #this is the frame for the directory
self.add_on_frm = tk.Frame(master=master)
self.add_on_frm.grid(row=1) #this is the frame for add-ons input
self.button_frm = tk.Frame(master=master)
self.button_frm.grid(row=2) #this is the frame for
#creates buttons, entries, labels
self.load_directory_frame() #creates and grids the directory button
self.load_add_on_frame() #creates and grids the entry buttons and labels
self.load_button_frame() #creates and grids the buttons
my_window.mainloop()
def load_add_on_frame(self):
vcmd = (self.master.register(self.validate_ent), '%S')
#create inputs and labels for add-ons
self.trip_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd, name='trip_ent')
self.trip_ent.grid(column= 1, row = 0)
self.raw_cutouts_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.raw_cutouts_ent.grid(column= 3, row = 0)
def clear_entries(self):
entries = (self.trip_ent, self.raw_cutouts_ent) #list of entries to loop (there are a total of 12 in the actual code)
for entry in entries:
entry.delete(0,len(entry.get())) #this is where the trouble seems to happen
new_quote = QuoteForm(my_window)
My problem is that the on the second to last line of code (starting with 'entry.delete')
Typically you would do 'entry.delete(0,END)' but because entry is a variable the code won't run with END.
'END' is an invalid index, and 'end' just does the same as pulling the length, and so i tried to make it dynamic by making the 'end' the length of whatever is in the entry.
When i do that however, it deletes nothing [i also tried forcing it with int(len(entry.get()))]. If i manually enter an integer it will delete everything up to that integer, including if it's the same as the length of that entry, and I put breaks to confirm that i'm getting an int return and I am.
I realize i could just write a line of code to delete each entry individually, but there's a totaly of 12 and I would like to clean it up.
I'm adding the full code to be able to run below
import os
import re
import tkinter as tk
from tkinter import filedialog as fd
from tkinter import messagebox
import pandas as pd
my_window = tk.Tk()
class QuoteForm():
def __init__(self,master):
self.file_data = ''
self.master = master
self.master.rowconfigure(0, weight=1)
self.master.rowconfigure(1, weight= 1)
self.master.rowconfigure(2, weight = 1)
master.geometry('600x400')
master.resizable(False,False)
self.directory_frm = tk.Frame(master=master)
self.directory_frm.grid(row=0) #this is the frame for the directory
self.add_on_frm = tk.Frame(master=master)
self.add_on_frm.grid(row=1) #this is the frame for add-ons input
self.button_frm = tk.Frame(master=master)
self.button_frm.grid(row=2) #this is the frame for
self.load_directory_frame()
self.load_add_on_frame()
self.load_button_frame()
my_window.mainloop()
#staticmethod
def get_quote_data(filepath):
#read csv to get job infomation for pricing
try:
if filepath:
job_info = pd.read_csv(filepath,
index_col=0, #set index column
skiprows=range(4), #skip first 4 rows
usecols=['Item','Quan'])
job_info = job_info.drop(labels='Grand Total:', axis= 0)
customer_info = pd.read_csv(filepath, header=None,
skiprows= lambda x: x not in range(2), #skip any row beyond first two rows
usecols=[0,1]) #use first two columns
customer_info = {customer_info.at[0,0].replace(':',''): customer_info.at[0,1], ##formatting the data for legibility
customer_info.at[1,0].replace(':','') : customer_info.at[1,1]}
return [customer_info, job_info]
except:
messagebox.showerror("Data Invalid", "Please make sure you select a valid estimate CSV file.")
def sink_check(self):
####this is to be used at the submit buttons to confirm that there are not more sinks than cutouts
cutouts = self.um_sink_inst_ent.get()
sink_quan_list = (self.std_sink_ent.get(),self.upgrd_sink_ent.get(),self.van_sink_ent.get(),self.cust_sink_temp_ent.get())
sinks = sum(sink_quan_list)
if sinks > cutouts:
return False
###check that the sinks included does not exceed the number of sinks charged for install
return True
def validate_ent(self,input):
if not input:
return True
elif re.fullmatch(r'[0-9]',input):
return True
return False
def open_file(self):
file = fd.askopenfile(mode='r', filetypes=[('CSV Files', '*.csv')])
if file:
filepath = os.path.abspath(file.name)
file_data = self.get_quote_data(filepath)
cust_name = file_data[0]['Name']
job_addr = file_data[0]['Addr']
self.file_select_text['text'] = f"{job_addr} for {cust_name} is currently selected"
def load_directory_frame(self):
file_select_btn = tk.Button(master=self.directory_frm,text= "Select a file",command=self.open_file)
file_select_btn.grid(column=0, row=0)
self.file_select_text = tk.Label(master=self.directory_frm, text = "No File Selected")
self.file_select_text.grid(column=1, row=0)
def load_add_on_frame(self):
vcmd = (self.master.register(self.validate_ent), '%S')
#create inputs and labels for add-ons
self.trip_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd, name='trip_ent')
self.trip_ent.grid(column= 1, row = 0)
self.raw_cutouts_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.raw_cutouts_ent.grid(column= 3, row = 0)
self.radii_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.radii_ent.grid(column= 1, row = 1)
self.arcs_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.arcs_ent.grid(column= 3, row = 1)
self.splay_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.splay_ent.grid(column= 1, row = 2)
self.wtrfall_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.wtrfall_ent.grid(column= 3, row = 2)
self.um_sink_inst_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.um_sink_inst_ent.grid(column= 1, row = 3)
self.farm_sink_co_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.farm_sink_co_ent.grid(column= 3, row = 3)
self.std_sink_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.std_sink_ent.grid(column= 1, row = 4)
self.upgrd_sink_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.upgrd_sink_ent.grid(column= 3, row = 4)
self.van_sink_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.van_sink_ent.grid(column= 1, row = 5)
self.cust_sink_temp_ent = tk.Entry(master=self.add_on_frm,validate = 'key', validatecommand = vcmd)
self.cust_sink_temp_ent.grid(column= 3, row = 5)
trip_lbl = tk.Label(master=self.add_on_frm,text = "Extra Trip(s)")
trip_lbl.grid(column= 0, row = 0)
raw_cutouts_lbl = tk.Label(master=self.add_on_frm,text = "Unpolished Cutout(s)")
raw_cutouts_lbl.grid(column= 2, row = 0)
radii_lbl = tk.Label(master=self.add_on_frm,text = "Radii")
radii_lbl.grid(column= 0, row = 1)
arcs_lbl = tk.Label(master=self.add_on_frm,text = "Arc(s)")
arcs_lbl.grid(column= 2, row = 1)
splay_lbl = tk.Label(master=self.add_on_frm,text = "Splay(s)")
splay_lbl.grid(column= 0, row = 2)
wtrfall_lbl = tk.Label(master=self.add_on_frm,text = "Waterfal Leg(s)")
wtrfall_lbl.grid(column= 2, row = 2)
um_sink_inst_lbl = tk.Label(master=self.add_on_frm,text = "Install of UM Sink(s)")
um_sink_inst_lbl.grid(column= 0, row = 3)
farm_sink_co_lbl = tk.Label(master=self.add_on_frm,text = "Farm Sink C/O")
farm_sink_co_lbl.grid(column= 2, row = 3)
std_sink_lbl = tk.Label(master=self.add_on_frm,text = "Standard 18ga Sink(s)")
std_sink_lbl.grid(column= 0, row = 4)
upgrd_sink_lbl = tk.Label(master=self.add_on_frm,text = "Upgrade 18ga Sink(s)")
upgrd_sink_lbl.grid(column= 2, row = 4)
van_sink_lbl = tk.Label(master=self.add_on_frm,text = "Vanity Sink(s)")
van_sink_lbl.grid(column= 0, row = 5)
cust_sink_temp_lbl = tk.Label(master=self.add_on_frm,text = "Customer Sink Template(s)")
cust_sink_temp_lbl.grid(column= 2, row = 5)
def load_button_frame(self):
submit_btn = tk.Button(master=self.button_frm, text='Submit')
submit_btn.grid(column=0,row=0)
clear_btn = tk.Button(master=self.button_frm,text='Clear',command=self.clear_entries)
clear_btn.grid(column=1, row=0)
advanced_btn = tk.Button(master=self.button_frm,text='Advanced')
advanced_btn.grid(column=2, row=0)
def clear_entries(self):
entries = (self.trip_ent, self.raw_cutouts_ent, self.radii_ent, self.arcs_ent, self.splay_ent, #list of entry boxes on the form
self.wtrfall_ent, self.um_sink_inst_ent, self.um_sink_inst_ent, self.farm_sink_co_ent,
self.std_sink_ent, self.upgrd_sink_ent, self.van_sink_ent, self.cust_sink_temp_ent)
for entry in entries:
entry.delete(0,tk.END)
new_quote = QuoteForm(my_window)
It's all about yourvalidate_ent function. Only when it returns true then your entry text can change. While typing tkinter just sent single chars like '1','2','a'. Even when you remove with backspace, this function gets the character you are trying to remove. However when you try to clear it function gets as an input whole string like '123543123'. This is not takes place inside r'[0-9]' reguler expression and you return false so tkinter denies removing it.
There is two simple solution to fix this.
First one add another condition for longer input like:
def validate_ent(self,input):
if not input:
return True
elif re.fullmatch(r'[0-9]',input):
return True
if(len(input)>2):
return True
return False
However I do not recommend this one because if someone copy paste longer inputs then it can write letters inside entry boxes.
def validate_ent(self,input):
if not input:
return True
elif re.fullmatch(r'[0-9]*',input):
return True
return False
In here we added a asteriks to reguler expression. Now it's accepting numbers bigger then 9. Now people can also paste numbers that fits into this rule. Also removing works as expected!

Listbox in Tkinter: output value based on input by using corresponding Excel columns

I'm aware that my code isn't very clean, , my primary focus at the moment is to make the program work.
I’m working with Tkinter and I created a search- and listbox based on a column in Excel. The Excelfile is imported by pandas, as a dataframe. The idea is that people can search for something (for example ‘Eiffel Tower’), that the value (‘Eiffel Tower’) is selected and that Python gives the construction date as output (so for example the year 1889) in the interface.
You search and make sure that the value is visible in the entrybox, and then you click on a button. After clicking on the button, you will see ‘1889’.
Both the buildings as the construction dates are listed in an Excelfile. Column A contains the buildings, column B contains the construction dates.
The search and listbox works. But I’m not ably to connect column A to column B, or to get an output based on the input that the uses gives.
The 'output_Startdate' was to test if the if-statement worked (what it does). The 'def connectie()' is me trying to find a solution.
My code:
import tkinter as tk
from tkinter import *
from tkinter import Listbox
from tkinter import ttk
import pandas as pd
interface = tk.Tk()
interface.configure(bg="#60c1c9")
interface.geometry('1500x750')
interface.title('Construction Dates')
title = Label(interface, text='1. BUILDINGS')
title.configure(bg="#60c1c9", fg="#000000", font=("Calibri", 20, "bold"))
title.place(relx=0.15, rely=0, anchor=N)
file_name = “List_Buildings.xlsx”
xl_workbook = pd.ExcelFile(file_name)
df = xl_workbook.parse(“Buildings”)
alist = df['MONUMENT'].tolist()
Startdate = df['Startdate'].tolist()
Enddate = df['Enddate'].tolist()
Label(
text="Select what you see on the picture.",
bg="#60c1c9",
fg="#000000",
font=("Calibri", 12)
).place(relx=0.29, rely=0.05, anchor=N)
def update(data):
my_list_1.delete(0, END)
for entry in data:
my_list_1.insert(END, entry)
def check(e):
typed = entry_1.get()
if typed == '':
data = alist
else:
data = []
for item in alist:
if typed.lower() in item.lower():
data.append(item)
update(data)
def fillout(e):
entry_1.delete(0, END)
entry_1.insert(0, my_list_1.get(ACTIVE))
entry_1 = Entry(interface, width=53)
entry_1.place(relx=0.205, rely=0.12, anchor=N)
entry_1.bind('<KeyRelease>', check)
my_list_1: Listbox = Listbox(interface, height=20, width=50)
my_list_1.place(relx=0.2, rely=0.15, anchor=N)
my_list_1.bind("<<ListboxSelect>>", fillout)
scrollbar_v = Scrollbar(interface, orient=VERTICAL, command=my_list_1.yview)
scrollbar_v.place(relx=0.301, rely=0.151, height=324)
scrollbar_h = Scrollbar(interface, orient=HORIZONTAL, command=my_list_1.xview)
scrollbar_h.place(relx=0.0985, rely=0.583, width=320.5)
#alist = df['MONUMENT'].tolist()
#output = df['Startdate'].tolist()
#df2 = pd.DataFrame(columns=['MONUMENT', 'Startdate', 'Enddate'])
#df2 = df.apply(lambda x: df['MONUMENT'] == df['Startdate'])
#print(df2)
def connectie():
value = entry_1.get()
for i in df['MONUMENT']:
if value == alist:
BLOCK_NAME.set(output)
return
def output_Startdate():
if entry_1.get() == ‘Eiffeltower’:
tekst = tk.Label(interface, text="good")
tekst.place(relx=0.3, rely=0.8)
else:
tekst = tk.Label(interface, text="this value doesn't excist")
tekst.place(relx=0.3, rely=0.8)
button = Button(interface, text='click here', command=output_Startdate)
button.place(relx=0.29, rely=0.7)
interface.mainloop()
I'm not sure what your data looks like (you didn't hand us a sample), so I hope I did it right. There are two parts to my answer, the first is for loading the file and setting the index column (I hope the names are all unique), and the second part is how to loc for the data you are looking for.
file_name = 'List_Buildings.xlsx' # file name
# read the file's Sheet1 and create dataframe with column 'MONUMENT' as index
df = pd.read_excel(file_name, 'Sheet1', index_col='MONUMENT')
# create alist from the index
alist = df.index.tolist()
def output_Startdate():
# get the entry_1 value
monument = entry_1.get()
# use monument (the entry_1 value) as index for dataframe loc and 'Startdate' as the column
start_date = df.loc[monument, 'Startdate']
# set the text for the label
tekst = tk.Label(interface, text=f"Start date: {start_date}")
tekst.place(relx=0.3, rely=0.8)

how to get the value of combobox selected item in python

selectedfood = tk.StringVar()
foodselectionUI = ttk.Combobox(homeUI, width = 27, textvariable = selectedfood)
foodselectionUI['values'] = ("None", "Nasi Ayam", "Maggi Mee Goreng", "Wan Tan Mee", "Nasi Lemak","Nasi Ayam Tiga Rasa", "Ayam Goreng", "Sushi", "Burger Special","Vega Bao", "Kari Ayam Bao","select food")
foodselectionUI.place(x = 10, y = 125, width = 150)
foodselectionUI.current(11)
this is my code 👆
and this picture is my tkinter UI👇
may i know how to get my selection
for example if user choose 'sushi' i can get it as my textvariable
i didnt get my output using this way
i get this thing PY_VAR1
def justamethod (*args):
print("method is called")
print (selectedfood.get())
foodselectionUIbind("<<ComboboxSelected>>", justamethod)

Why wont my code return a value for the data input into a tkinter text box

I have written this code and for some reason it refuses to return any sort of value or input for slef.REV when used in the function post(self) however it will return a value when I try and return a value in the getlen() function which is used to reurn the number of characters in the review.I dont have this problem for any other variables that I retrieve data from within this class. Below is the relevant code, any help would be appreciated. the lines where this problem occures is the first functio calld post(lines 1-5) and 4 lines up from the bottom
def post(self):
MovieID = self.MovID
REV = self.REV
AddReview(conn,cursor,Add_Review,MovieID,REV)
print(REV)
def shrek_film(self):
self.title = "Shrek"
self.MovID = 1
self.root4 = tk.Toplevel()
self.root4.title("Watch Shreck")
self.root4.geometry("1400x800")
frame_4 = tk.Frame(self.root4, bg = "black")
frame_4.pack(fill = tk.BOTH, expand = True, padx=0 , pady=0)
frame_4.grid_columnconfigure(1,weight=1)
self.Create_canvas = tk.Canvas(frame_4, width=2000, height=1080)
self.Create_canvas.place(x=-50, y=-50)
self.Create_img = PhotoImage(file="shrek-landscape.gif")
self.Create_canvas.create_image(20, 20, anchor = NW, image=self.Create_img)
play_button= tk.Button(frame_4,bg="orange",text="play", command = self.addHistory)
play_button.place(x=700,y=400)
play_button.config(font=("Ariel","30"))
def gtelen():
Review = reviewbox.get('1.0',END)
REVLEN = len(Review)
REVLENLEFT = (231-len(Review))
if REVLEN >=230:
lenbox = tk.Label(frame_4 ,text="No words left",bg="orange")
lenbox.place(x=360,y=460)
lenbox.config(font=("Ariel","15"))
else:
lenbox = tk.Label(frame_4 ,text=REVLENLEFT,bg="orange")
lenbox.place(x=360,y=460)
lenbox.config(font=("Ariel","15"))
print(Review)
Words_button = tk.Button(frame_4, bg="orange",text="check number of words remaining", command=gtelen)
Words_button.place(x=150,y=460)
Words_button.config(font=("Ariel","10"))
reviewlable=tk.Label(frame_4,text="Write a review",bg="orange")
reviewlable.place(x=10,y=460)
reviewlable.config(font=("ariel","15"))
Review_button= tk.Button(frame_4,bg="orange",text="See Reviews")#, command = self.ViewReviews)
Review_button.place(x=490,y=450)
Review_button.config(font=("Ariel","15"))
reviewbox= Text(frame_4,width=100,height=12)
reviewbox.place(x=10,y=500)
self.REV = reviewbox.get('1.0',END)
post_button = tk.Button(frame_4,bg="orange",text="Post Review", command = self.post)
post_button.place(x=830,y=650)
post_button.config(font=("Ariel","15"))
You can use Entry instead and use a StringVar
v = StringVar() # Create StringVar
reviewbox = Entry(frame_4, width = 100, height = 12, textvariable = v) # Create Entry widget
reviewbox.place(x = 10, y = 500) # Place Entry widget
self.REV = v.get() # Get contents of StringVar
The line self.REV = reviewbox.get('1.0',END) is being called about a millisecond after creating the text widget. The user will not even have seen the widget yet, much less have had time to type in it.
You can't call the get() method until after the user has had a chance to enter data, such as inside the post method.
def post(self):
MovieID = self.MovID
REV = reviewbox.get("1.0", "end")
AddReview(conn,cursor,Add_Review,MovieID,REV)
print(REV)

loop only appends on last button

I've made a gui with a variable amount of buttons and entries, dependent on earlier user inputs. I want to store the new entries in a list. My loop however will only append the last entry created in the loop. How can I get each button to append it's respective user entry?
def getFuseType():
(Fuse.fuseType).append(e.get()
print(Fuse.fuseType)
for i in range(1,int(Site.NoFuses)+1):
l = Label(FuseWindow, text = "Fuse Type")
e = Entry(FuseWindow)
l.grid(row = 1, column = i+3)
e.grid(row = 2, column = i+3)
b = Button(FuseWindow, text = "ok", command = getFuseType)
b.grid(row = 3, column = i+3)
Fuse GUI
see the image I've uploaded, The top right 'OK' button appends the entry. I want the top Left button to also append it's respective entry.
The problem is that the function isn't creating a closure around the e variable so they only affect the most recent (last) object assigned to e. If you really want to do this you'll need to use a defaulted arg..
for i in range(1,int(Site.NoFuses)+1):
l = Label(FuseWindow, text = "Fuse Type")
e = Entry(FuseWindow)
l.grid(row = 1, column = i+3)
e.grid(row = 2, column = i+3)
def getFuseType(e=e):
(Fuse.fuseType).append(e.get())
print(Fuse.fuseType)
b = Button(FuseWindow, text = "ok", command = getFuseType)
b.grid(row = 3, column = i+3)
Get getFuseType out of the for, it is defined every loop iteration and hence you only get the last create entry e
def getFuseType(ent):
Fuse.fuseType.append(ent)
print(Fuse.fuseType)
for i in range(1,int(Site.NoFuses)+1):
l = Label(FuseWindow, text = "Fuse Type")
e = Entry(FuseWindow)
ent = e.get()
l.grid(row = 1, column = i+3)
e.grid(row = 2, column = i+3)
b = Button(FuseWindow, text = "ok", command = lambda ent = ent:getFuseType(ent))
b.grid(row = 3, column = i+3)

Categories