Why is this update query not working in Python? - python

So I am creating a store management system that utilizes SQLite database.
When I execute the query directly in the SQLite browser, it works, but when I'm using Python, there is no error, but the update doesn't happen. Can you please take a look.
Part where I'm Updating with the left stock:
value1 = int(self.stock) - int(self.qne.get())
sql = "UPDATE products SET stock = " + str(value1) + " WHERE pk = " + str(self.ident.get())
conn.execute(sql)
conn.close()
My full code up to now:
# import random
from tkinter import *
import datetime
import sqlite3
conn = sqlite3.connect('database.db')
products_list = []
quantity_list = []
price_list = []
class Application:
def __init__(self, master):
self.master = master
# today's date
date = datetime.datetime.now()
# frames
self.left = Frame(master, width=800, height=700, bg='white')
self.left.pack(side=LEFT)
self.right = Frame(master, width=400, height=700, bg='steelblue')
self.right.pack(side=RIGHT)
# heading
self.heading = Label(self.left, text="Welcome to Store Management System", font=('arial 40 bold'), fg='steelblue', bg='white')
self.heading.place(x=0, y=0)
# cart
self.cart = Label(self.right, text=("TEST TRADE LINK"), font=('arial 25 bold'), fg='white', bg='steelblue', padx=10, pady=10)
self.cart.place(x=0, y=0)
# datelabel
self.datelabel = Label(self.right, text= (str(date)[:10]), font=('arial 25 bold'), fg='white', bg='steelblue')
self.datelabel.place(x=0,y=55)
# template for bill
self.bpro = Label(self.right, text= "Products", font=('arial 16 bold'), fg='white', bg='steelblue')
self.bpro.place(x=0, y=100)
self.bqua = Label(self.right, text= "Quantity", font=('arial 16 bold'), fg='white', bg='steelblue')
self.bqua.place(x=120, y=100)
self.bpri = Label(self.right, text= "Price", font=('arial 16 bold'), fg='white', bg='steelblue')
self.bpri.place(x=240, y=100)
# label for the input
self.id = Label(self.left, text="Enter Unique ID", font=('arial 16 bold'), bg='white')
self.id.place(x=0, y=80)
# entry for the unique id
self.inp = IntVar()
self.ident = Entry(self.left, width=50, bg='white', textvariable=self.inp)
self.ident.place(x=190, y=82)
# button
self.submit = Button(self.left, text="Submit", width=17, height=2, command=self.ajax)
self.submit.place(x=400, y=125)
# ajax contents
self.products_name = Label(self.left, text="", font=('arial 16 bold'), bg='white')
self.products_name.place(x=0, y=250)
self.price = Label(self.left, text="", font=('arial 16 bold'), bg='white')
self.price.place(x=0, y=290)
self.expiration = Label(self.left, text="", font=('arial 16 bold'), bg='white')
self.expiration.place(x=0, y=330)
# down reached upto y=440
self.total = Label(self.left, text="", font=('arial 16 bold'), bg='white')
self.total.place(x=0, y=480)
def ajax(self):
if self.ident.get() == "0":
print("Failed")
else:
self.result = conn.execute("SELECT * FROM products WHERE pk LIKE ?", [str(self.ident.get())])
for self.row in self.result:
self.product = self.row[1]
self.expd = self.row[4]
self.cost = self.row[3]
self.stock = self.row[2]
self.products_name.configure(text="Product Name: " + str(self.product))
self.price.configure(text="Price Per Unit: Rs. " + str(self.cost) + " \t")
self.expiration.configure(text="Expiration Date: " + str(self.expd))
# new labels and entries
self.qn = Label(self.left, text="Quantity", font=('arial 16 bold'), bg='white')
self.qn.place(x=0, y=370)
self.q = IntVar()
self.qne = Entry(self.left, width=50, bg='white', textvariable=self.q)
self.qne.place(x=150, y=371)
self.discount = Label(self.left, text="Discount", font=('arial 16 bold'), bg='white')
self.discount.place(x=0, y=410)
self.d = IntVar()
self.dise = Entry(self.left, width=50, bg='white', textvariable=self.d)
self.dise.place(x=150, y=410)
self.btnadd = Button(self.left, width=17, height=2, text="Add to Cart", bg='lightblue', command=self.add_to_cart)
self.btnadd.place(x=400, y=440)
self.bill = Button(self.left, width=17, height=2, text='Generate Bill', bg='lightgreen', command=self.print_bill)
self.bill.place(x=200, y=440)
def add_to_cart(self):
products_list.append(self.product)
quantity_list.append(self.qne.get())
price_list.append(int(self.qne.get()) * int(self.cost))
value1 = int(self.stock) - int(self.qne.get())
sql = "UPDATE products SET stock = " + str(value1) + " WHERE pk = " + str(self.ident.get())
conn.execute(sql)
conn.close()
t = 150
i = 0
for p in products_list:
self.pr1 = Label(self.right, text=str(products_list[i]), font=('arial 16 bold'), bg='steelblue', fg='white').place(x=0, y=t)
self.pr2 = Label(self.right, text=(str(quantity_list[i])), font=('arial 16 bold'), bg='steelblue', fg='white').place(x=120, y=t)
self.pr3 = Label(self.right, text=(str(price_list[i])), font=('arial 16 bold'), bg='steelblue', fg='white').place(x=240, y=t)
t += 40
i += 1
print(str(products_list) + str(quantity_list)+ str(price_list))
def print_bill(self):
f = open("bill.txt", 'w+')
f.write(str(products_list) + str(quantity_list) + str(price_list))
f.close()
# reset all after each purchase
# delete the temporary cart
del(products_list[:])
del(quantity_list[:])
del(price_list[:])
# # delete the labels
# self.pr1.configure(text="")
# self.pr2.configure(text="")
# self.pr3.configure(text="")
root = Tk()
b = Application(root)
# root.resizable(False, False)
root.geometry("1200x720+0+0")
root.mainloop()
I had 50 for the first product and I am trying to update it, but when I check it after the update is executed, it shows 50.
My database:

You have to explicitely commit the transaction (most client programs do it automagically for you but not the db-api modules):
value1 = int(self.stock) - int(self.qne.get())
sql = "UPDATE products SET stock = " + str(value1) + " WHERE pk = " + str(self.ident.get())
conn.execute(sql)
conn.commit()
conn.close()
Unrelated, but constructing sql queries that way is not only error prone (escaping issues notably) but also a huge security issue that leaves your code opened to SQL injections.
You want instead to use a cursor and let the db-api take care of properly building the query:
value = int(self.stock) - int(self.qne.get())
id = self.ident.get()
sql = "UPDATE products SET stock=? WHERE pk=?"
cursor = conn.cursor()
cursor.execute(sql, (value, id))
conn.commit()
This and the commit() call are actually well documented
Finally, opening a connection does not come for free so it's better to keep it open as long as possible instead of opening/closing it on each operation.

Related

Selecting multiple rows and fetching them simultaneously in treeview in tkinter

How can I select multiple rows in a treeview where in the treeview is pulling up data from MySQL database, so that I can display them in my text box. I am able to do this for one row at a time but not sure on how to select multiple entries. I basically have 2 frames in my GUI, left and right frames. Left frame shows a treeview with the animal names and right frame shows a text box. When someone selects the animal name and hit Add button, it should be added into the right text box. Just want to figure out on how to do this for multiple selections. Below is my code so far.
from tkinter import *
from tkinter import ttk
import pymysql
class Animals_App:
def __init__(self, root):
self.root = root
self.root.title("Animals")
self.root.geometry("1350x750+0+0")
self.root.resizable(FALSE, FALSE)
title = Label(self.root, text="Animals", font=("times new roman", 30, "bold"), bg="#262626",
fg="white").place(x=0, y=0, relwidth=1)
self.root.config(background="powder blue")
# =====Variables========
self.animal_var = StringVar()
# ==For displaying added Animal names on the right text box
def display_name():
txt_box.insert(END, 'Animal : ' + self.animal_var.get() + '\n')
# ==========Frame 1 (Left Frame)===========
Top_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Top_Frame.place(x=10, y=50, width=750, height=620)
Addbtn = Button(Top_Frame, padx=16, pady=1, bd=7, fg='black', font=('arial', 16, 'bold'), width=4,
text='Add', bg='powder blue', command=display_name).grid(row=0, column=0)
Table_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Table_Frame.place(x=10, y=130, width=750, height=620)
scroll_x = Scrollbar(Table_Frame, orient=HORIZONTAL)
scroll_y = Scrollbar(Table_Frame, orient=VERTICAL)
self.Animals_table = ttk.Treeview(Table_Frame,
columns=("animal"),
xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set)
scroll_x.pack(side=BOTTOM, fill=X)
scroll_y.pack(side=RIGHT, fill=Y)
scroll_x.config(command=self.Animals_table.xview)
scroll_y.config(command=self.Animals_table.yview)
self.Animals_table.heading("animal", text="Animal Names")
self.Animals_table['show'] = 'headings'
self.Animals_table.column("animal", width=100)
self.Animals_table.pack(fill=BOTH, expand=1)
self.Animals_table.bind("<ButtonRelease-1>", self.get_cursor)
self.fetch_data()
# ==========Frame 2 (Right Frame)===========
Txt_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Txt_Frame.place(x=770, y=70, width=580, height=620)
scroll_y = Scrollbar(Txt_Frame, orient=VERTICAL)
scroll_y.pack(fill=Y, side=RIGHT)
txt_box = Text(Txt_Frame, font=("times new roman", 15), bg="lightyellow", fg="black",
yscrollcommand=scroll_y.set)
txt_box.pack(fill=BOTH, expand=1)
scroll_y.config(command=txt_box.yview)
# txt_box.insert(END, 'Animal : ' + '\n')
def fetch_data(self):
con = pymysql.connect(host="localhost", user="root", password="", database="animaltree")
cur = con.cursor()
cur.execute("select * from animals")
rows = cur.fetchall()
# rows=["Cow","Deer","Dog","Zebra"]
if len(rows) != 0:
self.Animals_table.delete(*self.Animals_table.get_children())
for row in rows:
self.Animals_table.insert('', END, values=row)
con.commit()
con.close()
def get_cursor(self, ev):
cursor_row = self.Animals_table.focus()
contents = self.Animals_table.item(cursor_row)
row = contents['values']
self.animal_var.set(row[0])
root = Tk()
obj = Animals_App(root)
root.mainloop()
The default selection mode of Treeview is already in multiple mode. You need to use .selection() instead of .focus() to get the selected items.
In order to save the selections, change self.animal_var from StringVar() to Variable() and update display_name() and self.get_cursor() as below:
class Animals_App:
def __init__(self, root):
...
self.animal_var = Variable() # changed from StringVar()
def display_name():
txt_box.insert(END, 'Animal : ' + ', '.join(self.animal_var.get()) + '\n')
...
def get_cursor(self, ev):
self.animal_var.set([ev.widget.item(idx)['values'][0] for idx in ev.widget.selection()])

How to add Checkbox to every row of table to update/delete the row data from phpmyadmin in tkinter

May i know where and how do i need to do. I want to add a checkbox in every row and when it checked, the button of update or delete will only effect to the checked row.
I am new in python and currently i'm doing this for my project gui, is that anyone can help or if any suggestion you're welcome. Thanks
Below is my code:
from tkinter import *
from tkinter import messagebox
import mysql.connector
win = Tk()
win.title("Admin Signup")
win.geometry("750x400+300+90")
frame1 = Frame(win)
frame1.pack(side = TOP, fill=X)
frame2 = Frame(win)
frame2.pack(side = TOP, fill=X)
frame3 = Frame(win)
frame3.pack(side = TOP, padx = 10, pady=15)
frame4 = Frame(win)
frame4.pack(side = TOP, padx = 10)
frame5 = Frame(win)
frame5.pack(side = LEFT, padx = 10)
lbl_title = Label(frame1, text = "User List", font = ("BOLD 20"))
lbl_title.pack(side = TOP, anchor = "w", padx = 20, pady = 20)
btn_register = Button(frame2, text = "Register User")
btn_register.pack(side = TOP, anchor = "e", padx=20)
lbl01 = Label(frame3, text="Username", width=17, anchor="w", relief="raised")
lbl01.grid(row=0, column=0)
lbl02 = Label(frame3, text="Password", width=17, anchor="w", relief="raised")
lbl02.grid(row=0, column=1)
lbl03 = Label(frame3, text="Full Name", width=17, anchor="w", relief="raised")
lbl03.grid(row=0, column=2)
lbl04 = Label(frame3, text="Ic Number", width=17, anchor="w", relief="raised")
lbl04.grid(row=0, column=3)
lbl05 = Label(frame3, text="Staff Id", width=17, anchor="w", relief="raised")
lbl05.grid(row=0, column=4)
mydb = mysql.connector.connect(
host = "localhost",
user = "username",
password = "password",
database = "adminacc"
)
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM acc")
i = 0
for details in mycursor:
for j in range(len(details)):
e = Entry(frame4, width=17, relief=SUNKEN)
e.grid(row=i, column=j)
e.insert(END, details[j])
e.config(state=DISABLED, disabledforeground="blue")
i = i+1
btn_update = Button(frame5, text = "Update")
btn_update.grid(row=0, column=0, padx=15)
btn_delete = Button(frame5, text = "Delete")
btn_delete.grid(row=0, column=1)
win.mainloop()
Since every row behaves the same, suggest to use a class to encapsulate the behavior:
class AccountInfo:
def __init__(self, parent, details, row):
self.entries = []
# create entry box for each item in 'details'
for col, item in enumerate(details):
e = Entry(parent, width=17, relief=SUNKEN, disabledforeground='blue', bd=2)
e.grid(row=row, column=col)
e.insert(END, item)
e.config(state=DISABLED)
self.entries.append(e)
# create the checkbutton to select/deselect current row
self.var = BooleanVar()
Checkbutton(parent, variable=self.var, command=self.state_changed).grid(row=row, column=col+1)
def state_changed(self):
state = NORMAL if self.selected else DISABLED
# enable/disable entries except username
for e in self.entries[1:]:
e.config(state=state)
#property
def selected(self):
return self.var.get()
#property
def values(self):
return tuple(x.get() for x in self.entries)
Then using the class to create the required rows for each record retrieved from database:
mycursor.execute("SELECT * FROM acc")
accounts = [] # used to store the rows (accounts)
for row, details in enumerate(mycursor):
acc = AccountInfo(frame4, details, row)
accounts.append(acc)
The saved accounts can then be used in the callbacks of Update and Delete buttons:
def update_accounts():
for acc in accounts:
if acc.selected:
print(acc.values)
# do whatever you want on this selected account
btn_update = Button(frame5, text="Update", command=update_accounts)
Same logic on Delete button.
Note that you can modify the AccountInfo class to add functionalities that suit what you need.

tkinter searchbox for treeview python sqlite3

So I want to make a simple inventory system CRUD program. So far, I have been able to make it able to add new items, modify them and delete them. I'm lacking one last thing and that is to be able to search from a treeview which shows all of the items from the sqlite3 database. I wish to have a search box where i could just type in the name of the item and the program will print and select the items searched, which then i could do things such as modify or delete the selected items.
So far my code is:
from tkinter import Tk, Button, PhotoImage, Label, LabelFrame, W, E, N, S, Entry, END, StringVar, Scrollbar, Toplevel
from tkinter import ttk
import sqlite3
class Inventory:
db_filename = 'stock.db'
def __init__(self, root):
self.root = root
self.create_gui()
ttk.style = ttk.Style()
ttk.style.configure('Treeview', font=('helvetica',10))
ttk.style.configure('Treeview.Heading', font=('helvetica', 12, 'bold'))
def execute_db_query(self, query, parameters=()):
with sqlite3.connect(self.db_filename) as conn:
print(conn)
print('You have successfully connected to the Database')
cursor = conn.cursor()
query_result = cursor.execute(query, parameters)
conn.commit()
return query_result
def create_gui(self):
self.create_left_icon()
self.create_label_frame()
self.create_message_area()
self.create_tree_view()
self.create_scrollbar()
self.create_bottom_buttons()
self.view_items()
def create_left_icon(self):
photo = PhotoImage(file='./icons/logo.png')
label = Label(image=photo)
label.image = photo
label.grid(row=0, column=0)
def create_label_frame(self):
labelframe = LabelFrame(self.root, text='Input New Items', bg='sky blue', font='helvetica 10')
labelframe.grid(row=0, column=1, padx=8, pady=8, sticky='ew')
Label(labelframe, text='Name of Item:', bg='sky blue', fg='black').grid(row=1, column=1, sticky=W, pady=2, padx=15)
self.typefield = Entry(labelframe)
self.typefield.grid(row=1, column=2, sticky=W, padx=5, pady=2)
Label(labelframe, text='Stock Card ID:', bg='sky blue', fg='black').grid(row=2, column=1, sticky=W, pady=2, padx=15)
self.cardfield = Entry(labelframe)
self.cardfield.grid(row=2, column=2, sticky=W, padx=5, pady=2)
Label(labelframe, text='Count:', bg='sky blue', fg='black').grid(row=3, column=1, sticky=W, pady=2, padx=15)
self.countfield = Entry(labelframe)
self.countfield.grid(row=3, column=2, sticky=W, padx=5, pady=2)
Button(labelframe, text='Add', command=self.on_add_item_button_clicked, fg='black').grid(row=4, column=2, sticky=E, padx=5, pady=5)
def create_message_area(self):
self.message = Label(text='', fg='red')
self.message.grid(row=3, column=1, sticky=W)
def create_tree_view(self):
self.tree = ttk.Treeview(height=10, columns=('card', 'stock'), style='Treeview')
self.tree.grid(row=6, column=0, columnspan=3)
self.tree.heading('#0', text='Name of Item', anchor=W)
self.tree.heading('card', text='Stock Card ID', anchor=W)
self.tree.heading('stock', text='Count', anchor=W)
def create_scrollbar(self):
self.scrollbar = Scrollbar(orient='vertical', command=self.tree.yview)
self.scrollbar.grid(row=6, column=3, rowspan=10, sticky='sn')
def create_bottom_buttons(self):
Button(text='Delete', command=self.on_delete_selected_button_clicked).grid(row=8, column=0, sticky=W, pady=10, padx=20)
Button(text='Edit Stock', command=self.on_modify_selected_button_clicked).grid(row=8, column=1, sticky=W)
def on_add_item_button_clicked(self):
self.add_new_item()
def on_delete_selected_button_clicked(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['values'][0]
except IndexError as e:
self.message['text'] = 'Select at least one item to be deleted'
return
self.delete_items()
def on_modify_selected_button_clicked(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['values'][0]
except:
self.message['text'] = 'Select at least one item to be modified'
return
self.open_modify_window()
def add_new_item(self):
if self.new_items_validated():
query = 'INSERT INTO items_list VALUES(NULL, ?, ?, ?)'
parameters = (self.typefield.get(), self.cardfield.get(), self.countfield.get())
self.execute_db_query(query, parameters)
self.message['text'] = '{} has been added'.format(self.typefield.get())
self.typefield.delete(0, END)
self.cardfield.delete(0, END)
self.countfield.delete(0, END)
self.view_items()
else:
self.message['text'] = 'All entry field must be filled'
self.view_items()
def new_items_validated(self):
return len(self.typefield.get()) !=0 and len(self.cardfield.get()) != 0 and len(self.countfield.get()) != 0
def view_items(self):
items = self.tree.get_children()
for item in items:
self.tree.delete(item)
query = 'SELECT * FROM items_list ORDER BY TipeBarang'
item_entries = self.execute_db_query(query)
for row in item_entries:
self.tree.insert('', 0, text=row[1], values=(row[2], row[3]))
def delete_items(self):
self.message['text']=''
name = self.tree.item(self.tree.selection())['text']
query = 'DELETE FROM items_list WHERE TipeBarang = ?'
self.execute_db_query(query, (name,))
self.message['text'] = '{} has been deleted'.format(name)
self.view_items()
def open_modify_window(self):
name = self.tree.item(self.tree.selection())['text']
old_stock = self.tree.item(self.tree.selection())['values'][1]
self.transient = Toplevel()
self.transient.title('Update Stock')
Label(self.transient, text='Name: ').grid(row=0, column=1)
Entry(self.transient, textvariable=StringVar(
self.transient, value=name), state='readonly').grid(row=0, column=2)
Label(self.transient, text='Old Stock Count: ').grid(row=1, column=1)
Entry(self.transient, textvariable=StringVar(
self.transient, value=old_stock), state='readonly').grid(row=1, column=2)
Label(self.transient, text='New Stock Count: ').grid(row=2, column=1)
new_stock_number_entry_widget = Entry(self.transient)
new_stock_number_entry_widget.grid(row=2, column=2)
Button(self.transient, text='Update Item', command=lambda: self.update_stock(
new_stock_number_entry_widget.get(), old_stock, name)).grid(row=3, column=2, sticky=E)
self.transient.mainloop()
def update_stock(self, newstock, old_stock, name):
query = 'UPDATE items_list SET JumlahStok=? WHERE JumlahStok=? AND TipeBarang=?'
parameters = (newstock, old_stock, name)
self.execute_db_query(query, parameters)
self.transient.destroy()
self.message['text'] = '{} Stock Count has been updated'.format(name)
self.view_items()
if __name__ == "__main__":
root = Tk()
root.title("Inventory System")
root.resizable(width=False, height=False)
application = Inventory(root)
root.mainloop()
Below, I have also attached a screenshot of the program I have made so far. Thank you so much for your help.
Program Screenshot: https://i.stack.imgur.com/1kJch.png
There are a few different ways a search feature can be done here. You can add a search button that creates a Toplevel window and add widgets to it as needed. Or more simply, you can use simpledialog to get text input from the user like so:
queryString = simpledialog.askstring("Search", "Enter item name to search:")
Then pass the resulting queryString to a database function, sanitize it to prevent SQL injection, and SELECT * FROM table WHERE Item = 'queryString'
Then use the data returned from this query to populate your treeview.
def Search():
if SEARCH.get() != "":
tree.delete(*tree.get_children())
conn = sqlite3.connect("db_member.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM `member` WHERE `firstname` LIKE ? OR `lastname` LIKE ?", ('%'+str(SEARCH.get())+'%', '%'+str(SEARCH.get())+'%'))
fetch = cursor.fetchall()
for data in fetch:
tree.insert('', 'end', values=(data))
cursor.close()
conn.close()
this how you can search from Specific Column in Python with Sqlite3 and Tkinter, you have just to change tow things:
the Name of 'member', which is the Name of your created Table
firstname and lastname are the name of your columns, SEARCH.get() is the variable from the entry box

Python - Update GUI so it always uses the updated list

I have a project where I have multiple "Widgets" in a frame. I pass a list of Widgets onto a class called GUI which displays all these "Widgets". I have a button on my frame which needs to delete one of the widgets from the list. Which it does. But the widget itself does not disappear from the frame.
So to clarify
The GUI class has a list of objects [Object, Object, Object, Object]. So It now displays 4 Widget objects. When I press the delete button the new list looks like [Object, Object, Object] but the list in the GUI class is still [Object, Object, Object, Object]. How can I make it so the GUI always uses the newest version of the list?
The code to clarify
import random
from tkinter import *
import datetime
root = Tk()
root.configure(background="white")
root.title("Project 2.1")
Widgets = []
class GUI:
def __init__(self, widgets, master):
self.widgets = widgets
self.master = master
self.master.geometry("{0}x{1}+0+0".format(master.winfo_screenwidth(), master.winfo_screenheight()))
for widget in range(len(widgets)):
widgets[widget].widgetFrame.pack(side=LEFT, pady=20, padx=20, fill=Y)
if len(widgets) == 0:
NoInputLabel = Label(master, text="No modules connected, please connect a module", font='Helvetica 16 bold')
NoInputLabel.pack(side=TOP)
removeButton = Button(master, text="Remove widget", command=self.removeWidget)
removeButton.pack()
print(self.widgets)
def removeWidget(self):
self.widgets = self.widgets[:-1]
print(self.widgets)
class Widget:
def __init__(self, master, name):
self.master = master
self.name = name
colorArray = ["#e3e0f3", "#eebddd", "#80a3db", "#036fa0"]
self.widgetFrame = Frame(master, bg="white")
# widgetFrame.pack(side=LEFT, pady=20, padx=50)
widgetTop = Frame(self.widgetFrame, bg="white")
widgetTop.pack(side=TOP)
widgetCenter = Frame(self.widgetFrame, bg="white")
widgetCenter.pack(side=TOP)
widgetBottom = Frame(self.widgetFrame, bg="white")
widgetBottom.pack(side=TOP, fill=X)
self.WidgetName = Label(widgetTop, text=name, font='Helvetica 16 bold', bg=random.choice(colorArray))
self.WidgetName.pack(fill=X)
self.temperatureSliderLabel = Label(widgetTop, text="Temperature (°C)", bg="white")
self.temperatureSliderLabel.pack()
self.temperatureSlider = Scale(widgetTop, orient=HORIZONTAL, length=250, from_=0, to=40, bg="white")
self.temperatureSlider.pack()
self.lightSliderLabel = Label(widgetTop, text="Light Intensity (%)", bg="white")
self.lightSliderLabel.pack()
self.lightSlider = Scale(widgetTop, orient=HORIZONTAL, length=250, bg="white")
self.lightSlider.pack()
self.maxRolloutPositionLabel = Label(widgetTop, text="Rolling distance (cm): ", bg="white")
self.maxRolloutPositionLabel.pack()
self.maxRolloutEntry = Entry(widgetTop, bg="white")
self.maxRolloutEntry.pack(side=LEFT)
self.submitFormButton = Button(widgetTop, text="Submit", command=self.setSensors, bg="white")
self.submitFormButton.pack(side=LEFT)
self.openSunblindButton = Button(widgetCenter, text="Open sunblind", command=self.openSunblind, state=NORMAL,
bg="#28a745", fg="white")
self.openSunblindButton.pack(side=LEFT)
self.closeSunblindButton = Button(widgetCenter, text="Close sunblind", command=self.closeSunblind,
state=NORMAL, bg="#dc3545", fg="white")
self.closeSunblindButton.pack(side=LEFT)
self.setSunblindStatusButton = Button(widgetCenter, text="Automatic", command=self.setSunblindStatus,
bg="#6c757d", fg="white")
self.setSunblindStatusButton.pack(side=LEFT)
self.sunblindFrame = Frame(widgetBottom, bg="white")
self.sunblindFrame.pack(fill=X)
self.sunblindStatusLabel = Label(self.sunblindFrame, text="Sunblind status:", bg="white", anchor="w")
self.sunblindStatusLabel.pack(side=LEFT, pady=5)
self.sunblindStatus = Label(self.sunblindFrame, text="Manual", bg="white")
self.sunblindStatus.pack(side=RIGHT, pady=5)
self.temperatureFrame = Frame(widgetBottom, bg="white")
self.temperatureFrame.pack(fill=X)
self.temperatureValueLabel = Label(self.temperatureFrame, text="Temperature: ", justify=LEFT, bg="white",
anchor="w")
self.temperatureValueLabel.pack(side=LEFT, pady=5)
self.temperatureValue = Label(self.temperatureFrame, text="", bg="white")
self.temperatureValue.pack(side=RIGHT, pady=5)
self.lightSliderFrame = Frame(widgetBottom, bg="white")
self.lightSliderFrame.pack(fill=X)
self.lightSliderValueLabel = Label(self.lightSliderFrame, text="Light Intensity: ", justify=LEFT, bg="white",
anchor="w")
self.lightSliderValueLabel.pack(side=LEFT, pady=5)
self.lightSliderValue = Label(self.lightSliderFrame, text="", bg="white")
self.lightSliderValue.pack(side=RIGHT, pady=5)
self.rolloutFrame = Frame(widgetBottom, bg="white")
self.rolloutFrame.pack(fill=X)
self.rolloutLabel = Label(self.rolloutFrame, text="Roll-out position: ", justify=LEFT, bg="white", anchor="w")
self.rolloutLabel.pack(side=LEFT, pady=5)
self.rolloutValue = Label(self.rolloutFrame, text="", bg="white")
self.rolloutValue.pack(side=RIGHT, pady=5)
self.variable = StringVar(widgetBottom)
self.variable.set(self.name)
self.chooseArduino = OptionMenu(widgetBottom, self.variable, "Living Room", "Bedroom", "Study", "Sex Dungeon",
"Bingo club")
self.chooseArduino.pack()
self.setNameButton = Button(widgetBottom, text="Set name", command=self.setArduinoName)
self.setNameButton.pack()
def setSensors(self):
print("Set the temperature and light of the sensors")
self.temperatureValue.config(text=str(self.temperatureSlider.get()) + "°C")
self.temperature = self.temperatureSlider.get()
self.lightSliderValue.config(text=str(self.lightSlider.get()))
self.lightIntensity = self.lightSlider.get()
self.maxRolloutPositionLabel.config(text="Rolling distance (cm): " + str(self.maxRolloutEntry.get()))
def setName(self, widgetName):
self.widgetName = widgetName
def openSunblind(self):
print("Set the sunblind to an open state")
self.rolloutValue.config(text="Rolled out")
def closeSunblind(self):
print("Set the sunblind to an closed state")
self.rolloutValue.config(text="Rolled in")
def setSunblindStatus(self):
if self.setSunblindStatusButton.config('text')[-1] == 'Automatic':
self.openSunblindButton.config(state=DISABLED)
self.closeSunblindButton.config(state=DISABLED)
self.setSunblindStatusButton.config(text='Manual')
print("Sunblind is set to: " + self.setSunblindStatusButton['text'])
self.sunblindStatus.config(text="Automatic")
else:
self.openSunblindButton.config(state=NORMAL)
self.closeSunblindButton.config(state=NORMAL)
self.setSunblindStatusButton.config(text='Automatic')
print("Sunblind is set to: " + self.setSunblindStatusButton['text'])
self.sunblindStatus.config(text="Manual")
def setArduinoName(self):
self.WidgetName.config(text=self.variable.get())
def getTemperature(self):
return self.temperature
def getLightIntensity(self):
return self.lightIntensity
Arduino1 = Widget(root, "Arduino 1")
Arduino2 = Widget(root, "Arduino 2")
Arduino3 = Widget(root, "Arduino 3")
Arduino4 = Widget(root, "Arduino 4")
Arduino5 = Widget(root, "Arduino 5")
Widgets.append(Arduino1)
Widgets.append(Arduino2)
Widgets.append(Arduino3)
Widgets.append(Arduino4)
Widgets.append(Arduino5)
Visueel = GUI(Widgets, root)
root.mainloop()
Image
You could try something like
def removeWidget(self):
widget = self.widgets.pop()
widget.widgetFrame.pack_forget()
print(self.widgets)

Return variables from tkinter GUI to execute code and then print results to GUI

I am new to coding so please forgive me for any simple oversights.
I am writing a program that query's my local SQL database and returns basic statistics on the data. I am trying to build a simple tkinter GUI that will control the two variable factors and the print the results in text boxes.
I am currently stuck on getting the variables from the entry boxes.
I am using Python 3.6, my code is below.
Really appreciate any help.
from tkinter import *
from tkinter.ttk import *
import pandas as pd
import sqlalchemy as sc
engine = sc.create_engine("mssql+pyodbc://DC2:password#SQLconn")
class SimLvGUI(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.init_ui()
def init_ui(self):
self.parent.title("SimLv")
self.pack(fill=BOTH, expand=1)
lbl = Label(self, text="Enter FTR Source Sink")
lbl.grid(row=0, column=0, sticky=N + W, pady=4, padx=5)
entry1 = Entry(self)
entry1.grid(row=1, column=0, columnspan=1, padx=5, sticky=N + W)
lb2 = Label(self, text="Enter FTR Month as Number")
lb2.grid(row=2, column=0, sticky=N + W, pady=4, padx=5)
entry2 = Entry(self)
entry2.grid(row=3, column=0, columnspan=1, padx=5, sticky=N + W)
run_button = Button(self, text="Run")
run_button.grid(row=4, column=0, pady=4, padx=5, sticky=N + W)
run_button.config(command=self.on_button)
lb3 = Label(self, text="Historic spot FTR stats")
lb3.grid(row=5, column=0, padx=5, sticky=N + W)
results1 = Text(self, width=30)
results1.grid(row=6, column=0, rowspan=10, padx=5, sticky=W + N)
lb4 = Label(self, text="Historic FTR clearing stats")
lb4.grid(row=5, column=1, padx=5, sticky=N + W)
results2 = Text(self, width=30)
results2.grid(row=6, column=1, rowspan=10, padx=5, sticky=W + N)
lb5 = Label(self, text="Last FTR clearing price")
lb5.grid(row=5, column=2, padx=5, sticky=N + W)
results3 = Text(self, width=30, height=10)
results3.grid(row=6, column=2, rowspan=5, padx=5, sticky=W + N)
lb6 = Label(self, text="High volume FTR clearing price")
lb6.grid(row=11, column=2, padx=5, sticky=N + W)
results3 = Text(self, width=30, height=10)
results3.grid(row=12, column=2, rowspan=5, padx=5, sticky=W + N)
def on_button(self):
ftr_source_sink = self.entry1.get()
ftr_month = self.entry2.get()
def run_simlv(self):
sql1 = ("SELECT Avg({0}) as {0} "
"FROM dbo.FTR_matrix "
"WHERE month(Trading_date) = {1} "
"GROUP BY month(Trading_date), year(Trading_date) ORDER BY
year(Trading_date), month(Trading_date) "
.format(ftr_source_sink, ftr_month))
# Import FTR clearing data from SQL server.
sql2 = ("SELECT Price "
"FROM dbo.FTR_Reg "
"WHERE FTR = '{0}' and Mth = {1} and HedgeType = 'OPT' and MW>0 and
Price>0 "
"ORDER BY Mth, Yr ".format(ftr_source_sink, ftr_month))
# Return most recent FTR clearing price.
sql3 = ("SELECT DateAcquired, Mth, Yr, FTR, MW, Price "
"FROM (SELECT m.*, row_number() over (partition by FTR order by
DateAcquired desc) as rn "
"FROM dbo.FTR_Reg m "
"WHERE FTR = '{0}' and Mth = {1} and HedgeType = 'OPT' ) m2 "
"WHERE m2.rn = 1 ".format(ftr_source_sink, ftr_month))
# Return the highest volume FTR purchase
sql4 = ("SELECT DateAcquired, Mth, Yr, FTR, MW, Price "
"FROM (SELECT m.*, row_number() over (partition by FTR order by MW
desc) as rn "
"FROM dbo.FTR_Reg m "
"WHERE FTR = '{0}' and Mth = {1} and HedgeType = 'OPT' ) m2 "
"WHERE m2.rn `enter code here`= 1 ".format(ftr_source_sink, enter
code here ftr_month))
# Output historic spot statistics
print('Spot Price Statistics')
ftr_month_value = pd.read_sql_query(sql1, engine)
print(ftr_month_value.describe())
# Output historic clearing statistics
print('Clearing Price Statistics')
ftr_clearing = pd.read_sql_query(sql2, engine)
print(ftr_clearing.describe())
# Output last clearing price
print('Last Clearing Price')
ftr_lastprice = pd.read_sql_query(sql3, engine)
print(ftr_lastprice)
# Output highest volume cleared
print('Clearing Price at highest cleared volume')
ftr_high_volume = pd.read_sql_query(sql4, engine)
print(ftr_high_volume)
def main():
root = Tk()
root.geometry("900x600+200+50")
app = SimLvGUI(root)
root.mainloop()
if __name__ == '__main__':
main()
Your on_button does nothing practical because ftr_source_sink and ftr_month live and die inside your function definition. Try saving them as attributes:
def on_button(self):
self.ftr_source_sink = self.entry1.get()
self.ftr_month = self.entry2.get()
so that you later can access them anywhere inside the class definition.
As a side note, if you decide for this approach, it is usually good practice to initialize those attributes inside __init__:
def __init__(self, parent):
# your code
self.ftr_source_sink = None
self.ftr_month = None

Categories

Resources