Home > OS >  Remove curly brackets in tkinter list box
Remove curly brackets in tkinter list box

Time:07-20

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

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

On click

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]))
  • Related