Posts: 122
Threads: 16
Joined: Jul 2018
I had an issue with the results of my database query displaying curly brackets at the beginning and end of the results when it populated a tkinter widget. I found that if I change the insert string from output.insert(0,each_result) to output.insert(0,each_result[0]) it resolved the issue but it has raised a new issue.
The widget populated with the data now displays properly without the {} brackets but I can no longer click an item in that list displayed and run the query for that item.
The call to query the database for a selection made from the OptionMenu:
button = tkinter.Button(window_2, text="Load Category", font=('Times 9 bold'), bg = "#F9F8D6", fg = "#9A0615", command=select)
button.pack The query for the selection made from the OptionMenu:
def select():
try:
output.delete(0, END)
selection = var.get()
c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
results = c.fetchall()
for each_result in results:
output.insert(0,each_result[0])
except:
messagebox.showerror("DataBase Error", "Failed to load category") The results of this query works properly and I no longer have the curly brackets showing the beginning and end of each result in the list that is displayed.(adding the [0] in the insert line resolved that)
The binding for the displayed list to be clicked:
output = tkinter.Listbox(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615', selectmode=SINGLE)
output.pack()
output.place(x=210, y=200)
yscroll = tkinter.Scrollbar(command=output.yview, orient=tkinter.VERTICAL)
yscroll.place(x=450, y=200)
output.configure(yscrollcommand=yscroll.set)
output.bind('<ButtonRelease-1>', getRecipe) The procedure getRecipe to query the item in the displayed list when clicked:
This is the getRecipe procedure run when an item is clicked:
try:
dish_type_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
dish_type_results = c.fetchone()
dish_type_entry.insert(0,dish_type_results)
recipe_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Recipe FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
recipe_results = c.fetchone()
recipe_entry.insert(0,recipe_results[0])
serves_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Serves FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
serves_results = c.fetchone()\serves_entry.insert(0,serves_results[0])
cook_time_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Cook_Time FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
cook_time_results = c.fetchone()
cook_time_entry.insert(0,cook_time_results[0])
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Ingredients FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
ingredients_results = c.fetchone()
ingredients.insert(1.0,ingredients_results[0])
ingredients.config(wrap=WORD)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Instructions FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
instructions_results = c.fetchone()
instructions.insert(1.0, instructions_results[0])
instructions.config(wrap=WORD)
except:
messagebox.showerror("DataBase Error", "Failed to load category") This no longer populates the widgets and draws the error messagebox. This started when I added the [0] to the insert line of the for the selection made from the OptionMenu. (the second snip of code above)
Any advice and/or a point to documents that can explain why this is happening and how I can make the items in the displayed list clickable again without having the show the curly brackets would be appreciated.
"Often stumped... But never defeated."
Posts: 12,034
Threads: 486
Joined: Sep 2016
add the following in snippet labeled: The query for the selection made from the OptionMenu:
after line 7, and post (partial if large) results
print('each_result: {}'.format(each_result))
Posts: 122
Threads: 16
Joined: Jul 2018
Mar-08-2019, 04:16 AM
(This post was last modified: Mar-08-2019, 04:16 AM by DT2000.)
When I print the result of the query it provides the correct data, exactly as it is input in the column.
Print:
each_result: ("Sonic's Extreme Tots",)
each_result: ('Mozzarella Sticks',)
each_result: ('Loaded Potato Skins\r\n',)
each_result: ('Chile Con Queso\r\n',)
each_result: ('Buffalo Blasts',) The problem I am having it that without having the [0] at the end of the insert line in that query it populates the widget with each item having the curly bracket at the beginning and end of each item listed.
if I have the query as:
def select():
try:
output.delete(0, END)
selection = var.get()
c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
results = c.fetchall()
for each_result in results:
output.insert(0,each_result)
except:
messagebox.showerror("DataBase Error", "Failed to load category") This populates the widget as well but displays the curly brackets.
Example:
{Sonic's Extreme Tots}
{Mozzarella Sticks}
{Loaded Potato Skins}
and so on....
Only when I used the [o] in used the insert line did it remove the brackets, but then I cannot click one of the items displayed and have it load the data from the getRecipe query.
If I remove the [0] from the insert line and the curly brackets show again I can click an item and it will populate all fields properly.
"Often stumped... But never defeated."
Posts: 12,034
Threads: 486
Joined: Sep 2016
change line 8 from output.insert(0,each_result[0])
to output.insert(0,each_result.strip())
Posts: 122
Threads: 16
Joined: Jul 2018
I have added strip() to the line and it does the same as [0] to remove the curly brackets but it also prevents an item in the list to be actively clicked and populate the other widget.
When I remove the "try:' and comment out all but the first query to show me the problem I am getting the following from the getRecipe procedure:
File "C:\Users\Home\Documents\Python Projects\Recipe\3 Module\Recipe.py", line 158, in getRecipe
dish_type_entry.insert(1.0,dish_type_result)
tkinter.TclError: wrong # args: should be ".!entry insert index text But the query should be correct I think.
dish_type_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
dish_type_results = c.fetchone()
dish_type_entry.insert(0,dish_type_results) Any thoughts?
"Often stumped... But never defeated."
Posts: 12,034
Threads: 486
Joined: Sep 2016
It's very difficult without being able to run the code.
Since you have only provided snippets, that's not possible without a lot of work.
I'd only be guessing.
It sounds like it's treating the entire entry as a single item.
I do have some code on the forum that uses a listbox and works fine, you're welcome to take a look: https://python-forum.io/Thread-
California-Public-Salary-Files?highlight=public
code is here: https://github.com/Larz60p/CaliforniaPublicSalaries
Posts: 122
Threads: 16
Joined: Jul 2018
I will have a look at the links you provided... I truly appreciate the help.
I know that when the initial query is done (begins at line 174), it returns a tuple and that is the reason for the curly brackets showing on each item it fetched and populated in the widget.
I have now found the I can remove the curly brackets in a couple ways.
Adding [0] at the end of the insert line - output.insert(0,each_result[0])
or
Adding a comma in the "for" statement - for recipe, in results:
Either method changes the retrieved data from a tuple to a string variable.
The issue then become after it populates in the widget without the bracket and an item is then clicked the binding that goes to the query procedure "getRecipe()" to fetch the data for the item clicked no longer works.
Full code:
import os
import tkinter
import sqlite3
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
#================================ BEGIN PROGRAM ================================
def main():
#============================= CONNECT TO DATABASE =============================
conn = sqlite3.connect('Recipe.db')
c = conn.cursor()
#========================= CREATE DATABASE WITH TABLES =========================
c.execute('''CREATE TABLE IF NOT EXISTS Recipes(
Dish_Type CHAR(50) NOT NULL,
Recipe CHAR(50) NOT NULL,
Cook_Time CHAR(15) NOT NULL,
Serves CHAR(8) NOT NULL,
Ingredients CHAR(5000) NOT NULL,
Instructions CHAR(5000) NOT NULL);''')
conn.commit()
#================================= MAIN WINDOW =================================
root = tkinter.Tk()
root.title('Recipes')
w = 1024
h = 612
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.title('Recipes')
class OpenButton(Widget):
"""Button widget."""
def __init__(self, master=None, cnf={}, **kw):
start_button = tkinter.Button(root, text='Open', font='Times 12 bold italic', border = 2, bg = "#F9F8D6", fg = "#9A0615", width = 10, height = 2, command = window_2)
start_button.pack()
start_button.place(x=448, y=460)
#================================== MODULE 2 ===================================
def window_2():
root.destroy()
window_2 = tkinter.Tk()
w = 1024
h = 612
ws = window_2.winfo_screenwidth()
hs = window_2.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
window_2.geometry('%dx%d+%d+%d' % (w, h, x, y))
window_2.title('Recipes')
#============================== STRING VARIABLES ===============================
Recipe_Selection = StringVar()
Dish_Type = StringVar()
Recipe = StringVar()
Cook_Time = StringVar()
Serves = StringVar()
Ingredients = StringVar()
Instructions = StringVar()
#=========================== MODULE 2 CLEAR INPUT ==============================
def clear1():
output.delete(0,END)
instructions.delete(1.0,END)
#================================ RECIPE UPLOAD ================================
def save():
try:
c.execute('''INSERT INTO Recipes VALUES (?,?,?,?,?,?)''', (Dish_Type.get(), (Recipe.get()),
(Cook_Time.get()), (Serves.get()), (Ingredients.get()), (Instructions.get())))
conn.commit()
messagebox.showinfo("Information","Recipe saved successfully.")
except:
messagebox.showerror("Data Base Error", "Recipe was not saved.")
#=========================== MODULE 2 CLEAR INPUT ==============================
def clear2():
dish_type_entry.delete(0,END)
recipe_entry.delete(0,END)
serves_entry.delete(0,END)
cook_time_entry.delete(0,END)
ingredients.delete(1.0,END)
instructions.delete(1.0,END)
#============================== GET RECIPE QUERY ===============================
def getRecipe(event):
def clear2():
dish_type_entry.delete(0,END)
recipe_entry.delete(0,END)
serves_entry.delete(0,END)
cook_time_entry.delete(0,END)
ingredients.delete(1.0,END)
instructions.delete(1.0,END)
dish_type = tkinter.Label(window_2, font=('Times 9 bold'), text='Category:', bg = "#FFD599", fg = '#9A0615')
dish_type.pack()
dish_type.place(x=210, y=105)
dish_type_entry = tkinter.Entry(window_2, textvariable=Dish_Type, width = 20, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
dish_type_entry.place(x=288, y=106)
recipe = tkinter.Label(window_2, font=('Times 9 bold'), text='Recipe:', bg = "#FFD599", fg = '#9A0615')
recipe.pack()
recipe.place(x=210, y=125)
recipe_entry = tkinter.Entry(window_2, textvariable=Recipe, width = 20, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
recipe_entry.place(x=288, y=126)
serves = tkinter.Label(window_2, font=('Times 9 bold'), text='Serves:', bg = "#FFD599", fg = '#9A0615')
serves.pack()
serves.place(x=547, y=105)
serves_entry = tkinter.Entry(window_2, textvariable=Serves, width = 3, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
serves_entry.place(x=623, y=106)
cook_time = tkinter.Label(window_2, font=('Times 9 bold'), text='Cook Time:', bg = "#FFD599", fg = '#9A0615')
cook_time.pack()
cook_time.place(x=547, y=125)
cook_time_entry = tkinter.Entry(window_2, textvariable=Cook_Time, width = 11, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
cook_time_entry.place(x=623, y=126)
ingredients = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
ingredients.pack()
ingredients.place(x=210, y=200)
yscroll = tkinter.Scrollbar(command=ingredients.yview, orient=tkinter.VERTICAL)
yscroll.place(x=450, y=200)
ingredients.configure(yscrollcommand=yscroll.set)
instructions = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
instructions.pack()
instructions.place(x=547, y=200)
yscroll = tkinter.Scrollbar(command=instructions.yview, orient=tkinter.VERTICAL)
yscroll.place(x=787, y=200)
instructions.configure(yscrollcommand=yscroll.set)
dish_type_entry.focus()
clear1Button = tkinter.Button(window_2, text='Clear Page', font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615', command = clear2)
clear1Button.pack
clear1Button.place(x=630, y=527)
saveButton = tkinter.Button(window_2, text='Save Recipe', font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615')##, command = Save)
saveButton.pack
saveButton.place(x=293, y=527)
try:
dish_type_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
dish_type_result = c.fetchone()
dish_type_entry.insert(0,dish_type_result[0])
recipe_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Recipe FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
recipe_result = c.fetchone()
recipe_entry.insert(0,recipe_result[0])
serves_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Serves FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
serves_result = c.fetchone()
serves_entry.insert(0,serves_result[0])
cook_time_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Cook_Time FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
cook_time_result = c.fetchone()
cook_time_entry.insert(0,cook_time_result[0])
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Ingredients FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
ingredients_result = c.fetchone()
ingredients.insert(1.0,ingredients_result[0])
ingredients.config(wrap=WORD)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Instructions FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
instructions_result = c.fetchone()
instructions.insert(1.0, instructions_result[0])
instructions.config(wrap=WORD)
except:
messagebox.showerror("DataBase Error", "Failed to load category")
#================================ SELECT QUERY =================================
def select():
try:
output.delete(0, END)
selection = var.get()
c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
results = c.fetchall()
for each_result in results: ## ADD "," AFTER each_result TO CHANGE TO A STRING VARIABLE INSTEAD OF A TUPLE"
output.insert(0,each_result)## ADDING ".strip" DID NOT WORK
except:
messagebox.showerror("DataBase Error", "Failed to load category")
#================================ OPTION MENU ==================================
var = tkinter.StringVar(window_2)
var.set('Category')
choices = [
'Appetizers',
'Beef',
'Cake/Pastry',
'Desserts',
'Drinks',
'Eggs',
'Fish',
'Pasta',
'Pork',
'Potato',
'Poultry',
'Rice',
'Salads',
'Sandwiches',
'Sauces/Dips',
'Sea Food',
'Slow Cooker',
'Soups/Chilli',
'Spicy'
'Stews',
'Turkey',
'Vegetables']
option = tkinter.OptionMenu(window_2, var, *choices)
option.config(font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615')
option.place(x=210, y=157)
option["menu"].config(bg = '#F9F8D6', fg = '#9A0615')
backer = tkinter.Label(window_2, font=('Times 17 bold'), text=' ')
backer.pack()
backer.place(x=360, y=157)
button = tkinter.Button(window_2, text="Load Category", font=('Times 9 bold'), bg = "#F9F8D6", fg = "#9A0615", command=select)
button.pack
button.place(x=362, y=160)
#=============================== MENU PAGE WIDGETS =============================
instructions = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
instructions.pack()
instructions.place(x=547, y=200)
yscroll = tkinter.Scrollbar(command=instructions.yview, orient=tkinter.VERTICAL)
yscroll.place(x=787, y=200)
instructions.configure(yscrollcommand=yscroll.set)
output = tkinter.Listbox(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615', selectmode=SINGLE)
output.pack()
output.place(x=210, y=200)
yscroll = tkinter.Scrollbar(command=output.yview, orient=tkinter.VERTICAL)
yscroll.place(x=450, y=200)
output.configure(yscrollcommand=yscroll.set)
output.bind('<ButtonRelease-1>', getRecipe)
#=================================== BUTTONS ===================================
enterButton = tkinter.Button(window_2, text='Enter a Recipe', font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615')##, command = getRecipe())
enterButton.pack
enterButton.place(x=293, y=527)
clear1Button = tkinter.Button(window_2, text='Clear Page', font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615', command = clear1)
clear1Button.pack
clear1Button.place(x=630, y=527)
OpenButton()
root.mainloop()
if __name__ == '__main__':
main() The problem with this as I said is that once the tuple is change to a string variable by using either method, as I mentions above, I can no longer click on a recipe from the category list and have it query the "getRecipe()" procedure successfully.
(on a small separate note I am also trying to find the correct way to allow the Listbox at line 228 to again be viewable after getRecipe() has run. I naturally assume that I might want to select another category to view if I do not like the selection I initially make. So it needs to change from displaying the Text box back to the Listbox)
"Often stumped... But never defeated."
Posts: 12,034
Threads: 486
Joined: Sep 2016
Mar-09-2019, 09:22 AM
(This post was last modified: Mar-09-2019, 09:22 AM by Larz60+.)
I loaded the code into my IDE. but I won't get to this for a wkile, it's 4:20 A.M. and I've been up all night working on my own project.
If no one has answered by the time I wake up, I'll take a look at the code first thing.
Posts: 122
Threads: 16
Joined: Jul 2018
"Often stumped... But never defeated."
Posts: 122
Threads: 16
Joined: Jul 2018
I have found that the issue of the curly brackets has not been fully resolve.
I can remove the curly brackets by adding add a comma at line 8:
#================================ SELECT QUERY =================================
def select():
try:
output.delete(0, END)
selection = var.get()
c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
results = c.fetchall()
for each_result, in results: ## ADDED "," AFTER each result to remove the curly bracket when it inserts into widget.
output.insert(0,each_result)## ADDING ".strip" DID NOT WORK
except:
messagebox.showerror("DataBase Error", "Failed to load category") But as I said before it no longer allows the fetched data that is inserted into the widget to be actively clickable (from the binding), so it will query the database for the item clicked. If I leave the curly brackets then each item in the list is clickable and the query is done and fetches the data for the clicked item.
Having the brackets on each item after it populates the widget looks terrible and they need to be removed but keep it actively clickable.
I am not sure how to resolve this so any help or a point to literature that explains this would be greatly appreciated.
"Often stumped... But never defeated."
|