How to delete a specific occurrence with a delete button? - python

I have an iteration in my code which show for each line : ID / Name / Button Delete. You can see the image below. I would like when i click on one of the delete button that the data on the same line be deleted.
I try my best, you can see my code. How i can do it ?
Thank you a lot.
from tkinter import *
import mysql.connector
def main():
root = Tk()
conn = mysql.connector.connect(user='root', password='', host='localhost',
database='showmanager')
my_cursor = conn.cursor()
var_i = 3
def del_customer():
my_cursor.execute("DELETE FROM `spectator` "
"WHERE `spectator`.`id_customer` = "+user[0]+"")
my_cursor.execute("SELECT * FROM spectator")
users = my_cursor.fetchall()
for user in users:
label = Label(root, text=user, font=9)
label.grid(row=int(var_i), column=1)
Button(root, text="Delete spectator", font=9, height=1,
command=del_customer).grid(row=int(var_i), column=4)
var_i = var_i + 1
root.mainloop()
if __name__ == '__main__':
main()

You can pass the customer ID and corresponding widgets (label and button) to del_customer() so that you can remove the record in the database based on the customer ID and the corresponding label and button inside the function:
def del_customer(cust_id, widgets):
my_cursor.execute("DELETE FROM spectator WHERE id_customer = %s", [cust_id])
conn.commit() # make the change effective
# remove the corresponding label and button
for w in widgets:
w.destroy()
...
for user in users:
label = Label(root, text=user)
label.grid(row=var_i, column=1)
btn = Button(root, text="Delete spectator")
btn.grid(row=var_i, column=4)
var_i += 1
# pass the customer ID, label and button to del_customer()
btn['command'] = lambda cust_id=user[0], widgets=(label, btn): del_customer(cust_id, widgets)

Related

How do I pass variables from tkinter forms to different functions?

I'm trying to make an example for some high school students using tkinter with multiple forms, and accessing form data in different functions. I'm trying to keep the example simple, but having a small problem. The sv3 & sv4 variables are not getting the values from the second form. Any suggestions or ideas?
from tkinter import *
root = Tk()
sv1 = StringVar()
sv2 = StringVar()
sv3 = StringVar()
sv4 = StringVar()
#first function - this DOES NOT take text from entry widgets and displays, but should
def callback2():
test2 = sv3.get()
print(test2)
print (sv4.get())
print("show second form entry widgets values")
return True
#first function - this takes text from entry widgets and displays
def callback():
test = sv1.get()
print(test)
print (sv2.get())
print("show first form entry widgets values")
new_form()
return True
#new form
def new_form():
newfrm = Tk()
entry3 = Entry(newfrm, textvariable=sv3).pack()
entry4 = Entry(newfrm, textvariable=sv4).pack()
button = Button(newfrm, text="Click Me", command=callback2).pack()
newfrm.mainloop()
#initial form
def main_form():
entry1 = Entry(root, textvariable=sv1).pack()
entry2 = Entry(root, textvariable=sv2).pack()
button = Button(root, text="Click Me", command=callback).pack()
root.mainloop()
main_form()
Here how to avoid using multiple Tk instances and manually transfers the values from the first two Entrys to the second pair. See lines with #### comments.
from tkinter import *
root = Tk()
sv1 = StringVar()
sv2 = StringVar()
sv3 = StringVar()
sv4 = StringVar()
#first function - this now take text from entry widgets and displays as it should.
def callback2():
test2 = sv3.get()
print(test2)
print (sv4.get())
print("show second form entry widgets values")
return True
#first function - this takes text from entry widgets and displays
def callback():
test = sv1.get()
print(test)
print (sv2.get())
print("show first form entry widgets values")
new_form()
return True
#new form
def new_form():
#### newfrm = Tk()
newfrm = Toplevel() #### Instead.
sv3.set(sv1.get()) #### Trasfer value.
sv4.set(sv2.get()) #### Trasfer value.
entry3 = Entry(newfrm, textvariable=sv3).pack()
entry4 = Entry(newfrm, textvariable=sv4).pack()
button = Button(newfrm, text="Click Me", command=callback2).pack()
newfrm.mainloop()
#initial form
def main_form():
entry1 = Entry(root, textvariable=sv1).pack()
entry2 = Entry(root, textvariable=sv2).pack()
button = Button(root, text="Click Me", command=callback).pack()
root.mainloop()
main_form()

How to trigger a run button based on all the values in a list?

I have a Tkinter app and inside that app I have an OptionMenu which is giving me all the id's that are located in the list vehicleid. Please note that this list can become bigger or smaller.
Now I want my button to send the data of owner and vehicleid to a database based on what the user selects. So if I have for example 2 vehicleid's, I first need to select a specific vehicleid and for every vehicleid I need to select a specific owner.
So in case of 2 vehicleid my database should look like this:
vehicleid owner
C161 --- Spain
C162 --- United Kingdom
App looks like this:
This is my code:
owner = ['Spain', 'United Kingdom', 'Malaysia']
vehicleid = ['C161', 'C162']
window = Tk()
window.title("Running Python Script") # Create window
window.geometry('550x300') # Geo of the window
##These are the option menus
dd_owner = StringVar(window)
dd_owner.set(owner[0]) # the first value
w = OptionMenu(window, dd_owner, *owner)
w.grid(row=1, column=1)
dd_id = StringVar(window)
dd_id.set(vehicleid[0])
w0 = OptionMenu(window, dd_id, *vehicleid)
w0.grid(row=0, column=1)
##The run button
run_list_button =Button(window, text="Send data of ID's to database!")
run_list_button.grid(column=0, row=3)
##These are the titles
l1 = Label(window, text='Select Owner', width=15)
l1.grid(row=1, column=0)
l0 = Label(window, text='Select vehicle id:', width = 30)
l0.grid(row=0, column=0)
mainloop()
To begin with, you should store the data somewhere(a dictionary or a file..) and then read the data when the user presses the button.
import mysql.connector as mysql
....
mydb = mysql.connect(host = 'localhost',user = 'root',passwd = '****.',database = 'table_data')
data = {}
def store():
if dd_id.get() not in data:
data[dd_id.get()] = dd_owner.get()
print(data)
def upload():
cur = mydb.cursor()
for item in data.items():
sql = 'INSERT INTO table_data VALUES (%s,%s)'
params = (item[0],item[1])
cur.execute(sql,params)
mydb.commit()
print('Done')
....
# The store button
Button(window, text="Store data!",command=store).grid(column=0, row=3)
# The database button
Button(window, text="Send to database",command=upload).grid(column=0, row=4)
This will store the data in the database when the respective buttons are clicked, also duplicate entries or updatiion of entries will not be allowed.
Though your question is confusing. After looking at your discussion I understand that you want to send all data to the database only after the users have confirmed their choice.
In that case, you probably need a dictionary where you store both vehicle_id and owner {"vehicle_id": [], "owner": []} until the user clicks on the update database button. Once you have updated the database make sure to empty the dictionary so the previously selected items are not inserted into the database again.
Note: you would still need another button to be pressed several times to insert data into the dictionary. You can choose not to have the button by using the trace method of the control variable
Here is an example
from tkinter import *
import sqlite3
CREATE_QUERY = "CREATE TABLE IF NOT EXISTS vehicle(vehicle_id VARCHAR(5), owner VARCHAR(100));"
INSERT_QUERY = "INSERT INTO vehicle(vehicle_id, owner) VALUES(?, ?);"
SELECT_QUERY = "SELECT * FROM vehicle;"
sql_file = "sample.db"
id_dict = {"vehicle_id": [], "owner": []}
def create_data_base():
with sqlite3.connect(sql_file) as conn:
conn.execute(CREATE_QUERY)
conn.commit()
def insert_to_db():
global id_dict
with sqlite3.connect(sql_file) as conn:
for value in zip(*id_dict.values()):
conn.execute(INSERT_QUERY, value)
conn.commit()
id_dict = {"vehicle_id": [], "owner": []} # empty the list once you insert the data
display_data()
def display_data():
with sqlite3.connect(sql_file) as conn:
curr = conn.cursor()
curr.execute(SELECT_QUERY)
items = curr.fetchall()
print(items)
def add():
id_dict["vehicle_id"].append(dd_id.get())
id_dict["owner"].append(dd_owner.get())
print(id_dict)
owner = ['Spain', 'United Kingdom', 'Malaysia']
vehicleid = ['C161', 'C162']
window = Tk()
window.title("Running Python Script") # Create window
window.geometry('550x300') # Geo of the window
create_data_base()
##These are the option menus
dd_owner = StringVar(window)
dd_owner.set(owner[0]) # the first value
w = OptionMenu(window, dd_owner, *owner)
w.grid(row=1, column=1)
dd_id = StringVar(window)
dd_id.set(vehicleid[0])
w0 = OptionMenu(window, dd_id, *vehicleid)
w0.grid(row=0, column=1)
Button(window, text='Add', command=add).grid(column=1, row=3)
##The run button
run_list_button =Button(window, text="Send data of ID's to database!", command=insert_to_db)
run_list_button.grid(column=0, row=3)
##These are the titles
l1 = Label(window, text='Select Owner', width=15)
l1.grid(row=1, column=0)
l0 = Label(window, text='Select vehicle id:', width = 30)
l0.grid(row=0, column=0)
window.mainloop()
The above code will insert all the data from the dictionary to the database.

How can I set some password length restrictions using python?

Here is where I believe I would put the code for the restrictions
def savePassword():
os.system("Email.py")
if txt.get() == txt1.get():
# encode password for hashing
hashedPassword = hashPassword(txt.get().encode("utf-8"))
# insert masterpassword into database
insert_password = """INSERT INTO masterpassword(password)
VALUES(?) """
cursor.execute(insert_password, [hashedPassword])
sql_command = 'INSERT INTO details (email) VALUES(?) ' # Query
email = txt3.get()
cursor.execute(sql_command, [email])
db.commit()
passwordVault()
else:
lbl2.config(text="Passwords do not match")
i'd like it so that if the password does not reach a length requirement of say 7
Entry widget has validate and validatecommand that can do this job.
Here's an example code:
from tkinter import *
def check(ch):
return len(ch) <= 7 or ch==''
root = Tk()
ent = Entry(root, show='*')
ent.config(validate='key', validatecommand=(root.register(check), "%P"))
ent.pack()
root.mainloop()
update:
from tkinter import *
def savePasswd():
if len(ent.get())>7:
label['text'] = 'saved'
print("saved") # write save stmts here
else:
label['text']="Minimum length 7"
root = Tk()
label = Label(root)
label.pack()
ent = Entry(root, show='*')
ent.pack()
Button(root, text='save password', command=savePasswd).pack()
root.mainloop()

GUI-Tkinter-Python Program

How to create a button to open a new window in which all records are printed.
In the following part of program, i am unable to print records in a new window, but it gets printed in the already created window & the new window remains empty.
Here is that small part of program:-
root = Tk()
def query():
query = Tk()
query.title('Records')
query.iconbitmap(r'C:\Users\pankaj\Downloads\Elegantthemes-Beautiful-Flat-Document.ico')
query.geometry("450x350")
#Create a database or connect to one
conn = sqlite3.connect('Payslip.db')
# Create cursor
c = conn.cursor()
#Query the database
c.execute("SELECT *,oid from Payslip")
records = c.fetchall()
#print(records)# to print in the background
#Loop the results
print_records = ''
for record in records: #to show the records
print_records += str(record[0]) +"\t" + str(record[8])+ "\n"# \t to give space(tab) between them
query_label = Label(root, text=print_records)
query_label.grid(row=14, column=0, columnspan=2)
#Commit Change
conn.commit()
# Close Connection
conn.close()
#create a Query button
query_btn = Button(root, text="Show Records", command=query)
query_btn.grid(row=9,column=0, columnspan=2, pady=10, padx=10, ipadx=135)
Well, you are trying to print the print_records in the query_label, which you assigned to the root window:
query_label = Label(root, text=print_records)
You said you created a new window but I can't see it in the code, so you might want to do something like this:
def query():
top1 = Toplevel() # creates new window called top1
print_records = ''
for record in records: #to show the records
print_records += str(record[0]) +"\t" + str(record[8])+ "\n"
query_label = Label(top1, text=print_records) # now the query_label is assigned to top1
query_label.grid(row=14, column=0, columnspan=2)
However you want to do it:
query_label = Label(NEW_WINDOW, text=print_records)

Python / Tkinter - Error message when I try to save changes

I am building a database for tools and matrials list in Python using Tkinter for the GUI. I am running into issues when I try to edit data. Everything works until I click the save button in the editor window. It says: sqlite3.ProgrammingError: You did not supply a value for binding 1. Can anyone see what I am doing wrong here?
Here is my code:
from tkinter import *
import sqlite3
mud = Tk()
mud.title("Mud Data")
mud.geometry("400x600")
# Create database
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Create table
# c.execute("""CREATE TABLE mud (
# mud_type text,
# mud_weight real ,
# mud_viscosity real,
# mud_pit_number real
# )""")
# Create Submit Function for DB
def submit():
# Connect to DB
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Insert into table
c.execute("INSERT INTO mud VALUES (:mud_type, :mud_weight, :mud_viscosity, :mud_pit_number)",
{
'mud_type': mud_type.get(),
'mud_weight': mud_weight.get(),
'mud_viscosity': mud_viscosity.get(),
'mud_pit_number': mud_pit_number.get()
})
# Commit changes
conn.commit()
# Close connection
conn.close()
# Clear The Text Boxes
mud_type.delete(0, END)
mud_weight.delete(0, END)
mud_viscosity.delete(0, END)
mud_pit_number.delete(0, END)
# Function to edit a record
def edit():
# Create global variables
global editor
global mud_type_editor
global mud_weight_editor
global mud_viscosity_editor
global mud_pit_number_editor
editor = Tk()
editor.title("Edit mud")
editor.geometry("400x200")
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
record_id = delete_box.get()
c.execute("SELECT * FROM mud WHERE oid = " + record_id)
records = c.fetchall()
mud_type_editor = Entry(editor, width=30)
mud_type_editor.grid(row=0, column=1, pady=(10, 0))
mud_weight_editor = Entry(editor, width=30)
mud_weight_editor.grid(row=1, column=1)
mud_viscosity_editor = Entry(editor, width=30)
mud_viscosity_editor.grid(row=2, column=1)
mud_pit_number_editor = Entry(editor, width=30)
mud_pit_number_editor.grid(row=3, column=1)
# Create Text box Label
mud_type_label = Label(editor, text="Mud Type")
mud_type_label.grid(row=0, column=0, pady=(10, 0))
mud_weight_label = Label(editor, text="Mud Weight")
mud_weight_label.grid(row=1, column=0)
mud_viscosity_label = Label(editor, text="Mud Viscosity")
mud_viscosity_label.grid(row=2, column=0)
mud_pit_number_label = Label(editor, text="Mud Pit Number")
mud_pit_number_label.grid(row=3, column=0)
# Loop through results
for record in records:
mud_type_editor.insert(0, record[0])
mud_weight_editor.insert(0, record[1])
mud_viscosity_editor.insert(0, record[2])
mud_pit_number_editor.insert(0, record[3])
# Create save button
edit_button = Button(editor, text="Save Update", command=update)
edit_button.grid(row=7, column=1, pady=5, padx=5, ipadx=98)
conn.commit()
conn.close()
# Fucntion for updates
def update():
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
record_id = delete_box.get()
c.execute("""UPDATE mud SET
mud_type = :name,
mud_weight = :length,
mud_viscosity = :inside_diameter,
mud_pit_number = :outside_diameter
WHERE oid = :oid""",
{
'mud_type': mud_type_editor.get(),
'mud_weight': mud_weight_editor.get(),
'mud_viscosity': mud_viscosity_editor.get(),
'mud_pit_number': mud_pit_number_editor.get(),
'oid': record_id
})
conn.commit()
conn.close()
editor.destroy()
# Function to delete a record
def delete():
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
c.execute("DELETE FROM mud WHERE oid = " + delete_box.get())
conn.commit()
conn.close()
# Create Query Function
def query():
# Connect to DB
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Query the DB
c.execute("SELECT *, oid FROM mud")
records = c.fetchall()
# print(records)
# Loop through results
print_records = ''
for record in records:
print_records += str(record[0]) + "\t " + str(record[1]) + \
"\t " + str(record[2]) + "\t " + \
str(record[3]) + str(record[4]) + "\n"
query_label = Label(mud, text=print_records)
query_label.grid(row=20, column=0, columnspan=2)
# Commit changes
conn.commit()
# Close connection
conn.close()
# Math Functions
def volume_per_foot(bha_result_text):
bha_gallons_per_foot = float(mud_viscosity.get()) * \
float(mud_viscosity.get()) / 1029.4
bha_result_text.set(str(bha_gallons_per_foot))
# Create Text Boxes
mud_type = Entry(mud, width=30)
mud_type.grid(row=0, column=1, pady=(10, 0))
mud_weight = Entry(mud, width=30)
mud_weight.grid(row=1, column=1)
mud_viscosity = Entry(mud, width=30)
mud_viscosity.grid(row=2, column=1)
mud_pit_number = Entry(mud, width=30)
mud_pit_number.grid(row=3, column=1)
delete_box = Entry(mud, width=30)
delete_box.grid(row=6, column=1)
# Create Text box Label
mud_type_label = Label(mud, text="Mud Type")
mud_type_label.grid(row=0, column=0, pady=(10, 0))
mud_weight_label = Label(mud, text="Mud Weight")
mud_weight_label.grid(row=1, column=0)
mud_viscosity_label = Label(mud, text="Mud Viscosity")
mud_viscosity_label.grid(row=2, column=0)
mud_pit_number_label = Label(mud, text="Pit Number")
mud_pit_number_label.grid(row=3, column=0)
delete_box_label = Label(mud, text="Select ID")
delete_box_label.grid(row=6, column=0)
# Create Submit Button
submit_button = Button(mud, text="Save", command=submit)
submit_button.grid(row=4, column=1, pady=5, padx=5, ipadx=121)
# Create Query Button
query_button = Button(mud, text="Show Muds", command=query)
query_button.grid(row=5, column=1, pady=5, padx=5, ipadx=79)
# Create edit button
edit_button = Button(mud, text="Edit Muds", command=edit)
edit_button.grid(row=7, column=1, pady=5, padx=5, ipadx=87)
# Create delete button
delete_button = Button(mud, text="Delete Mud", command=delete)
delete_button.grid(row=8, column=1, pady=5, padx=5, ipadx=80)
# Commit changes
conn.commit()
# Close connection
conn.close()
mud.mainloop()
And here is the error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "mud.py", line 123, in update
c.execute("""UPDATE mud SET
sqlite3.ProgrammingError: You did not supply a value for binding 1.
Hi #LoudEye and welcome to Stack Overflow! Try using ? instead of : like this:
c.execute("UPDATE mud SET mud_type=?,mud_weight = ?, mud_viscosity=?, mud_pit_number = ? WHERE...",(mud_type_editor.get(), mud_weight_editor.get(),mud_viscosity_editor.get(),mud_pit_number_editor.get()))
Note: You should also use WHERE also with question mark like I've used with SET

Categories

Resources