Python Forum
[Tkinter] interlinked Comboboxes
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] interlinked Comboboxes
#1
Hi!

I'm trying to link two comboboxes but I'm running into the retrieval of the second one after selection.

---------------------- -------------------
| Table1 | | Table2 |
--------------------- -------------------
| table1Id | | table2Id |
|-------------------- |-----------------
| table1Name | | table2Name |
|-------------------- | ----------------
| table1Contact | | table1Id |

I would like that by selecting a value in list one, the elements linked to it are displayed in the second list and here's how I did it:

"""
Here's how i feed the 1st combobox
"""
def listProv():
qSallProv = 'SELECT DISTINCT provNom FROM prov;'
conn.execute(qSallProv)
provQR = conn.fetchall()
listProv = [prov[0] for prov in provQR]
return listProv

"""
Here's how i feed the 2nd combobox
"""
vNaissList = []
def listVille():
qSallVilleProv = "SELECT DISTINCT villeNom, provNom FROM ville AS v JOIN prov AS p ON p.provId = v.villeCodeProv WHERE provNom = '"+sel.get()+"';"
conn.execute(qSallVilleProv)
villeProvQR = conn.fetchall()
vNaissList = [ville[0] for ville in villeProvQR]
return vNaissList

"""
Getting the 1st combobox selected value
"""
sel = tk.StringVar()

"""
List of 1st combobox
"""
provNaissList = ttk.Combobox(labelInfoCiv, values=listProv(), textvariable=sel)
provNaissList.grid(row=3,column=0, sticky='ew')

"""
List of 2nd combobox
"""
villeNaissList = ttk.Combobox(labelInfoCiv, values=listVille())
villeNaissList.grid(row=4,column=0, sticky='ew')

sel.trace('w',villeNaissList)


The first list is ok and all i want appears but the second still be blank.

I don't know where i'm wrong.
buran write Dec-10-2024, 03:52 PM:
Please, use proper tags when post code, traceback, output, etc.
See BBcode help for more info.
Reply
#2
Although I'm using list instead of a database, maybe something like this

import tkinter as tk
from tkinter import ttk

list1 = [i for i in range(1, 5)]
list2 = [i for i in range(6, 11)]
list3 = [i for i in range(11, 16)]
list4 = [i for i in range(16, 21)]

root = tk.Tk()
root.configure(padx=5, pady=5)

def getlist(item):
    if item.get() == '1':
        box2.configure(values=list2)
    elif item.get() == '2':
        box2.configure(values=list3)
    elif item.get() == '3':
        box2.configure(values=list4)
    else:
        box2.configure(values=list2)
    
    box2.current(0)
    

myvar = tk.StringVar()

box1 = ttk.Combobox(font=(None, 14))
box1.pack(pady=5)
box1.configure(values=list1, textvariable=myvar)
box1.current(0)
box1.bind('<<ComboboxSelected>>', lambda event: getlist(myvar))

myvar2 = tk.StringVar()
box2 = ttk.Combobox(font=(None, 14))
box2.configure(values=list2, textvariable=myvar2)
box2.current(0)
box2.pack(pady=5)

root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags
Download my project scripts


Reply
#3
(Dec-10-2024, 04:57 PM)menator01 Wrote: Although I'm using list instead of a database, maybe something like this

import tkinter as tk
from tkinter import ttk

list1 = [i for i in range(1, 5)]
list2 = [i for i in range(6, 11)]
list3 = [i for i in range(11, 16)]
list4 = [i for i in range(16, 21)]

root = tk.Tk()
root.configure(padx=5, pady=5)

def getlist(item):
    if item.get() == '1':
        box2.configure(values=list2)
    elif item.get() == '2':
        box2.configure(values=list3)
    elif item.get() == '3':
        box2.configure(values=list4)
    else:
        box2.configure(values=list2)
    
    box2.current(0)
    

myvar = tk.StringVar()

box1 = ttk.Combobox(font=(None, 14))
box1.pack(pady=5)
box1.configure(values=list1, textvariable=myvar)
box1.current(0)
box1.bind('<<ComboboxSelected>>', lambda event: getlist(myvar))

myvar2 = tk.StringVar()
box2 = ttk.Combobox(font=(None, 14))
box2.configure(values=list2, textvariable=myvar2)
box2.current(0)
box2.pack(pady=5)

root.mainloop()

Thanks for your promptness! I came across something similar but I still can't figure it out because here the lists are defined statically but I have to retrieve them dynamically.
I tried with a loop but errors I show you the result

def getVilleProv(*args):
    ##-- on prépare le combobox à recevoir les données via la sélection du 1er combobox
    villeNaissList.set('')
    value = provNaissList.current()
    if value == '':
        villeNaissList['values'] = ''
    else:
        qSallVilleProv = "SELECT DISTINCT villeNom, provNom FROM ville AS v JOIN prov AS p ON p.provId = v.villeCodeProv WHERE provNom = %s;"
        conn.execute(qSallVilleProv, value)
        villeProvQR = conn.fetchall()
        vNaissList = [ville[0] for ville in villeProvQR]
        #villeNaissList['values'] = vNaissList
I can't figure out how to solve it.

By trying this:

#--- Liste1 --------------------------------------------------
def listProv():
    qSallProv = 'SELECT DISTINCT provNom FROM prov;'
    conn.execute(qSallProv)
    provQR = conn.fetchall()
    listProv = [prov[0] for prov in provQR]
    return listProv

#--- Liste2 -------------------
def listVille():
    qSallVilleProv = "SELECT DISTINCT villeNom, provNom FROM ville AS v JOIN prov AS p ON p.provId = v.villeCodeProv WHERE provNom = "+sel.get()+";"
    conn.execute(qSallVilleProv)
    villeProvQR = conn.fetchall()
    vNaissList = [ville[0] for ville in villeProvQR]
    return vNaissList

sel = tk.StringVar()

provNaissList = ttk.Combobox(labelInfoCiv, textvariable=sel, values=listProv())
provNaissList.grid(row=3,column=0, sticky='ew')

###--- Récupération de la valeur de la prov -------------------------------------------
provNaissList.current(0)

villeNaissList = ttk.Combobox(labelInfoCiv, values=listVille())
villeNaissList.grid(row=4,column=0, sticky='ew')

sel.trace('w',listVille)
I've an error:

Error:
Traceback (most recent call last): File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\.venv\Lib\site-packages\mysql\connector\connection_cext.py", line 706, in cmd_query self._cmysql.query( ~~~~~~~~~~~~~~~~~~^ query, ^^^^^^ ...<3 lines>... query_attrs=self.query_attrs, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ _mysql_connector.MySQLInterfaceError: Champ 'Estuaire' inconnu dans where clause The above exception was the direct cause of the following exception: Traceback (most recent call last): File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\frontend\main.py", line 94, in <module> villeNaissList = ttk.Combobox(labelInfoCiv, values=listVille()) ~~~~~~~~~^^ File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\frontend\main.py", line 38, in listVille conn.execute(qSallVilleProv) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^ File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\.venv\Lib\site-packages\mysql\connector\cursor_cext.py", line 357, in execute result = self._connection.cmd_query( stmt, ...<2 lines>... raw_as_string=self._raw_as_string, ) File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\.venv\Lib\site-packages\mysql\connector\opentelemetry\context_propagation.py", line 97, in wrapper return method(cnx, *args, **kwargs) File "D:\_Colab_Data_\SoftsDev\_PYTHON_\_SECURITE_\erp-gir\.venv\Lib\site-packages\mysql\connector\connection_cext.py", line 714, in cmd_query raise get_mysql_exception( err.errno, msg=err.msg, sqlstate=err.sqlstate ) from err mysql.connector.errors.ProgrammingError: 1054 (42S22): [b][color=#C0392B]Champ 'Estuaire'[/color] [/b]inconnu dans where clause Process finished with exit code 1
But we can see that the field that I put in bold in the error message is indeed data from combobox 1 which leads me to believe that I am not that far away.
Reply
#4
You have a query problem, not a combobox problem.

Forget about tkinter and see if you can get this code to work.
qSallVilleProv = "SELECT DISTINCT villeNom, provNom FROM ville AS v JOIN prov AS p ON p.provId = v.villeCodeProv WHERE provNom = "+sel.get()+";"
conn.execute(qSallVilleProv)
Hardcode a value for sel.get(). If you can get that to work, replace your hardcoded value with "". "" is what sel.get() will return until you select an item in the first combo box. I think you will see the same error you currently see.
Reply
#5
Modified code to work with database

import tkinter as tk
from tkinter import ttk
import sqlite3 as sq
 
# Create a dict of categories. This could be a query from a table if need be.
mydict = {'animal':'table1', 'fish':'table2', 'auto':'table3'}

def getit(table=None):
    ''' Function for getting data '''
    connect = sq.connect('test2.db')
    cursor = connect.cursor()
    query = f'select name from {table}'
    box2.configure(values=cursor.execute(query).fetchall())
    box2.current(0)
    

 
root = tk.Tk()
root.configure(padx=5, pady=5)   
 
myvar = tk.StringVar()
 
box1 = ttk.Combobox(font=(None, 14))
box1.pack(pady=5)
box1.configure(values=[key for key in mydict.keys()], textvariable=myvar)
box1.current(0)

# Bind combobox selection to function
box1.bind('<<ComboboxSelected>>', lambda event, val=myvar: getit(mydict.get(val.get())))


myvar2 = tk.StringVar()

box2 = ttk.Combobox(font=(None, 14))
box2.pack(pady=5)

# Call funtion to populate box2 on start
getit('table1')
 
root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags
Download my project scripts


Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Can't get tkinter database aware cascading comboboxes to update properly dford 6 5,773 Jan-11-2022, 08:37 PM
Last Post: deanhystad
  Linking Comboboxes MrP 24 10,956 Feb-03-2021, 10:59 PM
Last Post: MrP
  Print Values from a Sequence of Entries / ComboBoxes MC2020 4 4,672 Mar-28-2020, 10:05 PM
Last Post: MC2020
  [PyQt] making dependant comboBoxes Hitsugaya 3 6,244 May-23-2019, 06:05 PM
Last Post: Alfalfa

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020