GUI-Tkinter-Python Program - python

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)

Related

Python Tkinter text entry box to insert data to SQL Server

I have created a small python tkinter program designed to have a user write data into text entry boxes in the app then insert this data into a MS SQL server database. When clicking the insert button I am getting the following error message, stopping the app from insert the code into SQL.
cursor.execute("INSERT INTO TEST_DISA_MAIN_TABLE VALUES (:DENSITY_VALUE, :DATE, :TIME, :CHART_VALUE)",
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')*
This is my code for the python insert function:
def insertvalue():
# Create a database or connect to one
conn = pyodbc.connect('Driver={SQL Server};'
'Server=MON-SQL-02;'
'Database=ENVIRONMENTAL;'
'Trusted_Connection=yes;')
# Create cursor
cursor = conn.cursor()
# Insert into table
cursor.execute("INSERT INTO TEST_DISA_MAIN_TABLE VALUES (:DENSITY_VALUE, :DATE, :TIME, :CHART_VALUE)",
{
'DENSITY_VALUE': DENSITY_VALUE.get(),
'DATE': DATE.get(),
'TIME': TIME.get(),
'CHART_VALUE': CHART_VALUE.get(),
})
# Commit changes
conn.commit()
#Close Connection
conn.close()
# Clear the text boxes
DENSITY_VALUE.delete(0, END)
DATE.delete(0, END)
TIME.delete(0, END)
CHART_VALUE.delete(0, END)
#Create text boxes
DENSITY_VALUE = Entry(root, width=30)
DENSITY_VALUE.grid(row=2, column=1)
DATE = Entry(root, width=30)
DATE.grid(row=3, column=1)
TIME = Entry(root, width=30)
TIME.grid(row=4, column=1)
CHART_VALUE = Entry(root, width=30)
CHART_VALUE.grid(row=5, column=1)
#Create Text box labels
DENSITY_VALUE_Label = Label(root, text="Density Value")
DENSITY_VALUE_Label.grid(row=2, column=0)
DATE_Label = Label(root, text="Date")
DATE_Label.grid(row=3, column=0)
TIME_Label = Label(root, text="Time")
TIME_Label.grid(row=4, column=0)
CHART_VALUE_Label = Label(root, text="Chart Value")
CHART_VALUE_Label.grid(row=5, column=0)
button = Button(root, text = "Show All Values", command = showvalues)
button.grid(row=0, column=0)
button = Button(root, text = "Insert Values", command = insertvalue)
button.grid(row=1, column=0)
#Commit changes
conn.commit()
# Close connection
conn.close()
root.mainloop()
I used this format to insert data into a sqlite3 db, but the same format is not working when inserting into a SQL Server database. I have tested the connection to the SQL server and can display values in the app so that part works correctly.

How to create a search bar for a table from DB Browser

I'm trying to find a way to create a search bar for a table connected to a DB Browser database. The search bar I'm looking for is the one where you type in the bar, and the program will "hide" any data that does not follow the "requirements" while leaving the ones that do visible. The following code shows what I've tried so far. Hopefully, I made myself clear, and thank you for your help. I don't know how to attach the database so sorry for the inconvenience.
If you remove the code between the '''Triple Apostrophes,''' you should see a table with a button that says SELECT which reveals the data. The Table shown is where I would like the Search bar to control.
Thank you for your help once again.
from tkinter import ttk
import tkinter as tk
from tkinter import *
import sqlite3
ws = Tk()
ws.title('Directory')
ws.geometry('600x400')
ws.attributes('-topmost', True)
ws.attributes('-fullscreen', True)
'''
def Scankey(event):
val = event.widget.get()
print(val)
if val == '':
data = Table1
else:
data = []
for item in Table1:
if val.lower() in item.lower():
data.append(item)
Update(data)
def Update(data):
listbox.delete(0, 'end')
# put new data
for item in data:
listbox.insert('end', item)
ws = Tk()
entry = Entry(was)
entry.pack()
entry.bind('<KeyRelease>', Scankey)
listbox = Listbox(was)
listbox.pack()
Update()
# Connect to the database
def connect():
conn = sqlite3.connect("MEMBERinformation.db")
cur = conn.cursor()
cur.execute(
"CREATE TABLE IF NOT EXISTS ChurchMemberInformation(MemberID TEXT PRIMARY KEY, "
"FirstName TEXT, LastName TEXT)")
conn.commit()
conn.close()
# Populate Treeview table
def View():
conn = sqlite3.connect("MEMBERinformation.db")
cur = conn.cursor()
cur.execute("SELECT FirstName, LastName FROM ChurchMemberInformation")
rows = cur.fetchall()
for row in rows:
print(row) # print all records in the database
tree.insert("", tk.END, values=row)
conn.close()
#Frame
Table1 = Frame(was)
Table1.pack(anchor=CENTER)
# Connect the database
connect()
# Create Treeview widget
tree = ttk.Treeview(Table1, column=("column1", "column2",), show='headings')
tree['columns'] = ('FIRST NAME', 'LAST NAME')
tree.column('FIRST NAME', width=100)
tree.heading("#1", text="FIRST NAME")
tree.column('LAST NAME', width=100)
tree.heading("#2", text="LAST NAME")
tree.pack()
# Create and pack buttons
button1 = tk.Button(text="SELECT", command=View)
button2 = tk.Button(text="QUIT", command=ws.destroy)
button1.pack()
button2.pack()
ws.mainloop()

How to delete a specific occurrence with a delete button?

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)

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.

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