Hi I am trying to remove the curly brackets in the tkinter listbox
, however I need to maintain it as a tuple so when I use curselection
I can populate the entry
boxes.
Here is my code:
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
import sqlite3
def connect():
conn=sqlite3.connect("Section_25_GUI_and_Postgres/books2.db")
cur=conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title text, author text, year integer, isbn integer)")
conn.commit()
conn.close()
def insert(title, author, year, isbn):
conn=sqlite3.connect("Section_25_GUI_and_Postgres/books2.db")
cur=conn.cursor()
cur.execute("INSERT INTO book VALUES (NULL, ?, ?, ?, ?)", (title, author, year, isbn))
conn.commit()
conn.close()
def view():
conn=sqlite3.connect("Section_25_GUI_and_Postgres/books2.db")
cur=conn.cursor()
cur.execute("SELECT * FROM book")
rows=cur.fetchall()
conn.close()
return rows
# connect()
# insert("My Book 2", "Kevin Medri", 2020, 269494945)
def get_selected_row(event):
try:
global selected_tuple
index = li1.curselection()[0]
selected_tuple = li1.get(index)
print(selected_tuple)
e1.delete(0, END)
e1.insert(END, selected_tuple[1])
e2.delete(0, END)
e2.insert(END, selected_tuple[2])
e3.delete(0, END)
e3.insert(END, selected_tuple[3])
e4.delete(0, END)
e4.insert(END, selected_tuple[4])
except IndexError:
pass
def view_command():
li1.delete(0, END)
for row in view():
li1.insert(END, row)
def close_command():
window.destroy()
window = tk.Tk()
window.title('Book Case')
window.geometry('-50 50')
window.resizable(False, False)
window.attributes('-alpha',0.9)
window.configure(background='#d7e1ff')
# UI options
paddings = {'padx': 5, 'pady': 5}
entry_font = {'font': ('Arial', 10)}
# configure style globally for labels and buttons
window.style = Style(window)
window.style.configure('TLabel', anchor='e', background='#d7e1ff', font=('Arial', 10))
window.style.configure('TButton', anchor='w', background='#d7e1ff', font=('Arial', 10))
l1 = Label(window, text='Title', **entry_font)
l1.grid(row=0, column=0, **paddings)
l2 = Label(window, text='Author', **entry_font)
l2.grid(row=0, column=2, **paddings)
l3 = Label(window, text='Year', **entry_font)
l3.grid(row=1, column=0, **paddings)
l3 = Label(window, text='ISBN', **entry_font)
l3.grid(row=1, column=2, **paddings)
title_text = StringVar()
e1 = Entry(window, textvariable=title_text, **entry_font)
e1.grid(row=0, column=1, **paddings)
author_text = StringVar()
e2 = Entry(window, textvariable=author_text, **entry_font)
e2.grid(row=0, column=3, **paddings)
year_text = StringVar()
e3 = Entry(window, textvariable=year_text, **entry_font)
e3.grid(row=1, column=1, **paddings)
isbn_text = StringVar()
e4 = Entry(window, textvariable=isbn_text, **entry_font)
e4.grid(row=1, column=3, **paddings)
li1 = Listbox(window, height=13, width=35, **entry_font)
li1.grid(row=2, column=0, rowspan=6, columnspan=2, **paddings)
sb1 = ttk.Scrollbar(window, orient='vertical', command=li1.yview)
sb1.grid(row=2, column=2, rowspan=6, sticky=tk.NS, **paddings)
li1.configure(yscrollcommand=sb1.set)
sb1.configure(command=li1.yview)
li1.bind('<<ListboxSelect>>', get_selected_row)
b1 = ttk.Button(window, text='View All', command=view_command)
b1.grid(row=2, column=3, **paddings)
b6 = ttk.Button(window, text='Close', command=close_command)
b6.grid(row=7, column=3, **paddings)
window.mainloop()
Here is result of my code when I click on View All
I need the entry boxes to fill when I click on one of the items in the list box but with no curly brackets in the listbox
CodePudding user response:
Basically the reason for {}
appearing is already explained: I am getting { } on the end of my output. What is causing this and how do I remove it?
Now when you convert it to a string with ' '.join(map(str, row)))
you will notice, it is fine. But when you try to insert it into the entry boxes, you will face problem because it is no longer a tuple
, it is a str
and using e1.insert(END, selected_tuple[1])
wont work the way you expect.
So you need a way to convert the string back to a tuple. So you could use something like selected_tuple = selected_tuple.split(' ')
. But here you are splitting with every empty space. And there can be empty space between each item AND also inside the same item too, like My Book Two
. So what you can do is, create two versions, one where each element is split using ' '
and other where it is split using '-'
and create a link between them:
{ 'this is item one': 'this-is-item-one' }
Then your view function will be like:
def view_command():
li1.delete(0, END)
for row in view():
items_hyphen = '-'.join(map(str, row)) # Hyphened
items_space = ' '.join(map(str, row)) # Spaced
li1.insert(END, items_space)
mapper[items_space] = items_hyphen # Add to dictionary
And your get function will be like:
def get_selected_row(event):
try:
index = event.widget.curselection()
selected_item_space = li1.get(index) # Get string from listbox
selected_item_hyphen = mapper[selected_item_space] # Get corresponding hyphenated value from dictionary
selected_list = selected_item_hyphen.split('-')[1:] # Slide to remove the ID
ents = [e1, e2, e3, e4]
for ent, value in zip(ents, selected_list): # Loop through `ents` and `selected_list` at the same time
ent.delete(0, END) # Clear
ent.insert(END, value) # Then insert
except IndexError:
pass
Alternatively, instead of using hyphened value, you could store the tuple itself as said by @acw1668:
def get_selected_row(event):
try:
...
selected_item_tuple = mapper[selected_item_space] # Get corresponding tuple from dictionary
...
for ent,value in zip(ents, selected_item_tuple):
...
except IndexError:
pass
def view_command():
li1.delete(0, END)
for row in view():
items_space = ' '.join(map(str, row)) # Spaced
li1.insert(END, items_space)
mapper[items_space] = row # Add to dictionary
CodePudding user response:
The problem is that you're trying to insert a tuple into a listbox, since each row is a tuple of the values from each individual column.
The listbox expects a string rather than a tuple, so it uses tcl's internal converter to convert the tuple to a string. For values in the tuple that have spaces or a few other special characters, tcl will place curly braces around the elements.
You should explicitly convert the tuple to a string before passing it to the listbox insert
method so that this doesn't happen. One way to do that is to convert each row to a list by joining the list elements with a space (or any other character)
For example, the following example converts each row to a string by converting each column to a string, and then joining the columns together with a space.
def view_command():
li1.delete(0, END)
for row in view():
li1.insert(END, " ".join([str(column) for column in row]))