SM23
SM23

Reputation: 409

Load Listbox Selection into Entry Box with Sqlite3 Connection

I've built a listbox in Tkinter connected to Sqlite and have different functions with button commands connected to the database which work fine (such as Add, Fetch, Save, etc.) The only control I am having trouble executing is selecting the database entries displaying in my Listbox after I Fetch them from the database. For sake of simplicity, this is my current code just for the Fetch and Load sections:

#Fetch all database records to display in listbox
def fetchRecord():
    cont = sqlite3.connect('storagetest.db')
        with cont:
        cursort = cont.cursor()
        list_loadr = cursort.execute('''SELECT name FROM content''')
        list_load = list_loadr.fetchall()
        for item in list_load:
            list.insert(END, item)

        cont.commit()

#Load is supposed to select content and insert into Entry field
def loadRecord():
    cont = sqlite3.connect('test.db')
    c = cont.cursor()
    c.execute('SELECT * FROM content')
    for item in c:
        list.get(list.curselection())
    cont.commit()
    print ("select")

Basically, I'm having trouble binding the (single) selection in the Listbox and outputting it into an entry box. The shell ouputs no errors, only my print function above outputs. I've been able to find how to do this using a grid layout instead of pack, but without a db connection. However the rest of my gui geometry, buttons and rows are in pack geometry layout. Does anyone know if it's even necessary to have the database connected and executed in this case? I'm pretty lost on this one and haven't seen many resources in regards to using both Sqlite3 and Tkinter out there. Thank you in advance for any help.

Upvotes: 0

Views: 3286

Answers (2)

SM23
SM23

Reputation: 409

The links above were helpful in leading in the right direction and I was able to find the solution to this. It required me to convert into a grid geometry layout instead of a pack geometry layout for more functionality and modularity in selecting and returning the text entries. The event bindings needed to be separated upon selecting a list item and returning it within the text field box. Again, confirming that Sqlite database connection was not required for this functionality as stated above by Rolf.

#Bind listbox selection into entry field 
def get_list(event):
    index = listbox1.curselection()[0]
    seltext = listbox1.get(index)
    enter1.delete(0, 50)
    enter1.insert(0, seltext)

#Bind entry text into listbox    
def set_list(event):
    try:
        index = listbox1.curselection()[0]
        listbox1.delete(index)
    except IndexError:
        index = tk.END
    listbox1.insert(index, enter1.get())

listbox1 = tk.Listbox(root, width=50, height=6)
listbox1.grid(row=0, column=0)

enter1 = tk.Entry(root, textvariable=source, width=50)
enter1.insert(0, 'Click on Fetch Button, then select item in the listbox')
enter1.grid(row=1, column=0)

enter1.bind('<Return>', set_list)
enter1.bind('<Double-1>', set_list)

listbox1.bind('<ButtonRelease-1>', get_list)

This resource link here was somewhat of a good example of what I was looking to achieve (except with Sqlite db connection commands).

Upvotes: 3

Rolf of Saxony
Rolf of Saxony

Reputation: 22438

You haven't performed a fetch, so you have no data.
Use:

mydata = c.fetchone()

or

mydata = c.fetchall()

and then you can say

for item in mydata:

for the record, the commit statement is only used to commit writes to the database.
The reason for no information about Tkinter and sqlite3 is because they have no relationship. A simple search for sqlite3 and python will provide a mountain of documentation.

Edit 1: to clarify after your comment
You still need to do a fetch after the select. So your code should be something like this:

def loadRecord():
    cont = sqlite3.connect('test.db')
    c = cont.cursor()
    c.execute('SELECT * FROM content')
    mydata = c.fetchall()
    for row in mydata:
        list.get(row)

I haven't used Tkinter for a long time so I'm not sure about the list.get(row) line but whatever it should be you will be loading your data from the "fetched" data i.e. mydata
To pull out individual data items in the for loop set the "dictionary cursor":

cont.row_factory = sqlite3.Row

and thereafter you can access the data using the column names, like so:

for row in mydata:
    print row['data_item1']
    print row['data_item2']

Where data_item1 and data_item2 are the names (fields) in your database table

to test it try printing mydata or row in the for row in mydata loop

Finally, with regard to the commit statement, no in this case you do not require it. However, you can set the database to automatic commits, so that you do not have to worry about them by setting the isolation_level when you open the database:

sqlite3.connect("mydatabase.db", isolation_level=None)

Upvotes: 1

Related Questions