Posts: 10
Threads: 3
Joined: Aug 2023
Aug-27-2023, 05:28 AM
(This post was last modified: Aug-28-2023, 03:06 AM by Larz60+.)
Hi everyone
I am using customtkinter to make some comboboxes
Basically I have a list of Groups, which have their own corresponding models and buckets available
see the dictionaries below please
models_data = {
"Caterpillar LHD models": {
"R1300G": ["DB 3.4", "DB 2.8", "DB 2.5", "DB 3.1"],
"R1600H": ["DB 5.9", "DB 4.8", "DB 4.2", "DB 5.6"],
"R1700": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5", "DB 8"],
"R1700XE": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5"],
"R1700G": ["DB 4.6", "DB 5", "DB 6.6", "DB 5.7", "DB 7.3", "DB 8.8"],
"R2900G": ["DB 8.9", "DB 7.2", "DB 6.3", "DB 8.3"],
"R2900": ["DB 6.3", "DB 7.2", "DB 8.3", "DB 8.9"],
"R2900XE": ["DB 7.4", "DB 8.6", "DB 9.2", "DB 9.8"],
"R3000H": ["DB 10.5", "DB 8.9", "DB 9.5"]
},
"Sandvik LHD models": {
"SANDVIK LH517i": ["DB 7", "DB 7.6", "DB 8.6", "DB 9.1", "DB 8.4"],
"SANDVIK LH621i": ["DB 8.0", "DB 9.0", "DB 10.7", "DB 11.2"],
"SANDVIK LH515i": ["DB 6.3", "DB 6.8", "DB 7.5"],
"SANDVIK LH514": ["DB 6.2", "DB 7", "DB 5.4"],
"Toro™ LH625iE": ["DB 10"],
"Sandvik LH514E": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7"],
"Toro™ LH514BE": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7", "DB 7.5"],
"Sandvik LH409E": ["DB 3.8", "DB 4.3", "DB 4.6"]
},
"Epiroc LHD models": {
"Epiroc ST14 SG": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 SG": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"],
"Epiroc ST14": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 S": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"]
},
"Komatsu LHD models": {
"WX18H": ["DB 8.2", "DB 9.2", "DB 10", "DB 11.2"],
"WX22H": ["DB 10", "DB 11", "DB 12.2", "DB 13.8"]
}
So I have setup some definitions as such
def on_group_selected(col):
selected_group = group_vars[col].get()
model_dropdowns[col]['values'] = list(models_data[selected_group].keys())
model_vars[col].set("")
buckets_dropdowns[col]['values'] = []
def on_model_selected(col):
selected_group = group_vars[col].get()
selected_model = model_vars[col].get()
if selected_model != "":
bucket_values = models_data[selected_group][selected_model]
buckets_dropdowns[col]['values'] = bucket_values
I have setup the labels as such
# Group dropdown
group_var = ctk.StringVar()
group_var.set(list(models_data.keys())[col])
group_vars.append(group_var)
group_dropdown = ctk.CTkComboBox(column_frame, variable=group_var, values=list(models_data.keys()),font=("Univers-Light-Normal", 10), width=200, justify="center", command=on_model_selected)
group_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_group_selected(col))
group_dropdown.pack(pady=10)
# Model dropdown
model_var = ctk.StringVar()
model_var.set("Select Model")
model_vars.append(model_var)
model_dropdown = ctk.CTkComboBox(column_frame, variable=model_var, values=[], font=("Univers-Light-Normal", 10), width=200)
model_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_model_selected(col))
model_dropdown.pack(pady=10)
model_dropdowns.append(model_dropdown)
# Buckets dropdown
buckets_var = ctk.StringVar()
buckets_var.set("")
buckets_dropdown = ctk.CTkComboBox(column_frame, variable=buckets_var, values=[],font=("Univers-Light-Normal", 10) ,width=80)
buckets_dropdown.pack(pady=10)
buckets_dropdowns.append(buckets_dropdown)
My Group drop down works, the model dropdown and buckets don't work, essentially no list to select from
Can someone please help me out?
Thank you!
Larz60+ write Aug-28-2023, 03:06 AM:Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Posts: 1,145
Threads: 114
Joined: Sep 2019
Please use bb tags when posting. It helps with the formatting.
Posts: 10
Threads: 3
Joined: Aug 2023
Aug-27-2023, 06:02 AM
(This post was last modified: Aug-27-2023, 06:05 AM by Sedos101.)
[quote="Sedos101" pid='172259' dateline='1693114093']
Hi everyone
I am using customtkinter to make some comboboxes
Basically I have a list of Groups, which have their own corresponding models and buckets available
see the dictionaries below please
models_data = {
"Caterpillar LHD models": {
"R1300G": ["DB 3.4", "DB 2.8", "DB 2.5", "DB 3.1"],
"R1600H": ["DB 5.9", "DB 4.8", "DB 4.2", "DB 5.6"],
"R1700": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5", "DB 8"],
"R1700XE": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5"],
"R1700G": ["DB 4.6", "DB 5", "DB 6.6", "DB 5.7", "DB 7.3", "DB 8.8"],
"R2900G": ["DB 8.9", "DB 7.2", "DB 6.3", "DB 8.3"],
"R2900": ["DB 6.3", "DB 7.2", "DB 8.3", "DB 8.9"],
"R2900XE": ["DB 7.4", "DB 8.6", "DB 9.2", "DB 9.8"],
"R3000H": ["DB 10.5", "DB 8.9", "DB 9.5"]
},
"Sandvik LHD models": {
"SANDVIK LH517i": ["DB 7", "DB 7.6", "DB 8.6", "DB 9.1", "DB 8.4"],
"SANDVIK LH621i": ["DB 8.0", "DB 9.0", "DB 10.7", "DB 11.2"],
"SANDVIK LH515i": ["DB 6.3", "DB 6.8", "DB 7.5"],
"SANDVIK LH514": ["DB 6.2", "DB 7", "DB 5.4"],
"Toro™ LH625iE": ["DB 10"],
"Sandvik LH514E": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7"],
"Toro™ LH514BE": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7", "DB 7.5"],
"Sandvik LH409E": ["DB 3.8", "DB 4.3", "DB 4.6"]
},
"Epiroc LHD models": {
"Epiroc ST14 SG": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 SG": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"],
"Epiroc ST14": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 S": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"]
},
"Komatsu LHD models": {
"WX18H": ["DB 8.2", "DB 9.2", "DB 10", "DB 11.2"],
"WX22H": ["DB 10", "DB 11", "DB 12.2", "DB 13.8"]
} So I have setup some definitions as such
def on_group_selected(col):
selected_group = group_vars[col].get()
model_dropdowns[col]['values'] = list(models_data[selected_group].keys())
model_vars[col].set("")
buckets_dropdowns[col]['values'] = []
def on_model_selected(col):
selected_group = group_vars[col].get()
selected_model = model_vars[col].get()
if selected_model != "":
bucket_values = models_data[selected_group][selected_model]
buckets_dropdowns[col]['values'] = bucket_values I have setup the labels as such
# Group dropdown
group_var = ctk.StringVar()
group_var.set(list(models_data.keys())[col])
group_vars.append(group_var)
group_dropdown = ctk.CTkComboBox(column_frame, variable=group_var, values=list(models_data.keys()),font=("Univers-Light-Normal", 10), width=200, justify="center", command=on_model_selected)
group_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_group_selected(col))
group_dropdown.pack(pady=10)
# Model dropdown
model_var = ctk.StringVar()
model_var.set("Select Model")
model_vars.append(model_var)
model_dropdown = ctk.CTkComboBox(column_frame, variable=model_var, values=[], font=("Univers-Light-Normal", 10), width=200)
model_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_model_selected(col))
model_dropdown.pack(pady=10)
model_dropdowns.append(model_dropdown)
# Buckets dropdown
buckets_var = ctk.StringVar()
buckets_var.set("")
buckets_dropdown = ctk.CTkComboBox(column_frame, variable=buckets_var, values=[],font=("Univers-Light-Normal", 10) ,width=80)
buckets_dropdown.pack(pady=10)
buckets_dropdowns.append(buckets_dropdown) My Group drop down works, the model dropdown and buckets don't work, essentially no list to select from
Can someone please help me out?
Thank you!
Posts: 10
Threads: 3
Joined: Aug 2023
(Aug-27-2023, 05:30 AM)menator01 Wrote: Please use bb tags when posting. It helps with the formatting.
Hi I have updated, any chance you can help please?
Thanks you
Posts: 6,804
Threads: 20
Joined: Feb 2020
Aug-27-2023, 11:38 AM
(This post was last modified: Aug-28-2023, 12:15 PM by deanhystad.)
You need to update the model list when the group selection changes. Same goes with updating the bucket list when you select a model. You tried to do this, but didn't succeed, primarily because of this:
group_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_group_selected(col)) This sets up your software to call on_group_selected when the user makes a selection. Sounds good, but it is not what you want. What you really want is to call on_group_selected whenever the selection is set, either by clicking on a item, or by setting the string variable associated with the combo box. You want to use StringVar.trace():
import tkinter as tk
import tkinter.ttk as ttk
models_data = {
"Caterpillar LHD models": {
"R1300G": ["DB 3.4", "DB 2.8", "DB 2.5", "DB 3.1"],
"R1600H": ["DB 5.9", "DB 4.8", "DB 4.2", "DB 5.6"],
"R1700": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5", "DB 8"],
"R1700XE": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5"],
"R1700G": ["DB 4.6", "DB 5", "DB 6.6", "DB 5.7", "DB 7.3", "DB 8.8"],
"R2900G": ["DB 8.9", "DB 7.2", "DB 6.3", "DB 8.3"],
"R2900": ["DB 6.3", "DB 7.2", "DB 8.3", "DB 8.9"],
"R2900XE": ["DB 7.4", "DB 8.6", "DB 9.2", "DB 9.8"],
"R3000H": ["DB 10.5", "DB 8.9", "DB 9.5"]
},
"Sandvik LHD models": {
"SANDVIK LH517i": ["DB 7", "DB 7.6", "DB 8.6", "DB 9.1", "DB 8.4"],
"SANDVIK LH621i": ["DB 8.0", "DB 9.0", "DB 10.7", "DB 11.2"],
"SANDVIK LH515i": ["DB 6.3", "DB 6.8", "DB 7.5"],
"SANDVIK LH514": ["DB 6.2", "DB 7", "DB 5.4"],
"Toro™ LH625iE": ["DB 10"],
"Sandvik LH514E": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7"],
"Toro™ LH514BE": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7", "DB 7.5"],
"Sandvik LH409E": ["DB 3.8", "DB 4.3", "DB 4.6"]
},
"Epiroc LHD models": {
"Epiroc ST14 SG": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 SG": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"],
"Epiroc ST14": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 S": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"]
},
"Komatsu LHD models": {
"WX18H": ["DB 8.2", "DB 9.2", "DB 10", "DB 11.2"],
"WX22H": ["DB 10", "DB 11", "DB 12.2", "DB 13.8"]
}
}
class ComboBox(ttk.Combobox):
"""A convenient Combobox."""
def __init__(self, *args, command=None, **kwargs):
self.value = tk.StringVar()
self.value.trace("w", command)
super().__init__(
*args, textvariable=self.value, **kwargs
)
def set_values(self, values):
"""Set values in list."""
self["values"] = values
if values:
self.set(values[0])
def get(self):
"""Return value."""
return self.value.get()
def set(self, value):
"""Set value."""
self.value.set(value)
class Column(tk.Frame):
"""Controls for selecting a loader"""
def __init__(self, *args, command=None, width=30, **kwargs):
super().__init__(*args, **kwargs)
self.command = command
self.group = ComboBox(
self, values=list(models_data), command=self._group_cb, width=width
)
self.model = ComboBox(self, command=self._model_cb, width=width)
self.bucket = ComboBox(self, command=self._bucket_cb, width=width)
self.group.pack(pady=10)
self.model.pack(pady=10)
self.bucket.pack(pady=10)
def _group_cb(self, *_):
"""Group selection changed. Update model dropdown."""
self.model.set_values(list(models_data[self.group.get()]))
def _model_cb(self, *_):
"""Model selection changed. Update bucket dropdown."""
self.bucket.set_values(list(models_data[self.group.get()][self.model.get()]))
def _bucket_cb(self, *_):
"""Bucket selection changed. Execute selection callback command."""
if self.command:
self.command(self.selection())
def selection(self):
"""Return selected manufacturer, model, bucket."""
return self.group.get(), self.model.get(), self.bucket.get()
class Window(tk.Tk):
def __init__(self):
super().__init__()
width = max(len(key) for key in models_data)
for group in models_data:
column = Column(self, command=print, width=width)
column.pack(side=tk.LEFT, padx=10, pady=10)
column.group.set(group)
Window().mainloop()
Posts: 10
Threads: 3
Joined: Aug 2023
(Aug-27-2023, 11:38 AM)deanhystad Wrote: You need to update the model list when the group selection changes. Same goes with updating the bucket list when you select a model.
Can you please tell show me how to do that?
Posts: 6,804
Threads: 20
Joined: Feb 2020
Aug-27-2023, 02:04 PM
(This post was last modified: Aug-27-2023, 02:04 PM by deanhystad.)
See above.
And please post runnable examples that demonstrate the problem.
Posts: 10
Threads: 3
Joined: Aug 2023
Aug-28-2023, 01:12 AM
(Aug-27-2023, 02:04 PM)deanhystad Wrote: See above.
And please post runnable examples that demonstrate the problem.
THANK YOU SOO MUCH!!
Posts: 10
Threads: 3
Joined: Aug 2023
Hi I just realised you changed the code from ctk.CTkCombobox to the regular tk.Combobox
are you able to do this in the ctk.CTkCombobox instead please?
(Aug-27-2023, 11:38 AM)deanhystad Wrote: You need to update the model list when the group selection changes. Same goes with updating the bucket list when you select a model. You tried to do this, but didn't succeed, primarily because of this:
group_dropdown.bind("<<ComboboxSelected>>", lambda event, col=col: on_group_selected(col)) This sets up your software to call on_group_selected when the user makes a selection. Sounds good, but it is not what you want. What you really want is to call on_group_selected whenever the selection is set, either by clicking on a item, or by setting the string variable associated with the combo box. You want to use StringVar.trace():
import tkinter as tk
import tkinter.ttk as ttk
models_data = {
"Caterpillar LHD models": {
"R1300G": ["DB 3.4", "DB 2.8", "DB 2.5", "DB 3.1"],
"R1600H": ["DB 5.9", "DB 4.8", "DB 4.2", "DB 5.6"],
"R1700": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5", "DB 8"],
"R1700XE": ["DB 5.7", "DB 6.1", "DB 6.6", "DB 7.5"],
"R1700G": ["DB 4.6", "DB 5", "DB 6.6", "DB 5.7", "DB 7.3", "DB 8.8"],
"R2900G": ["DB 8.9", "DB 7.2", "DB 6.3", "DB 8.3"],
"R2900": ["DB 6.3", "DB 7.2", "DB 8.3", "DB 8.9"],
"R2900XE": ["DB 7.4", "DB 8.6", "DB 9.2", "DB 9.8"],
"R3000H": ["DB 10.5", "DB 8.9", "DB 9.5"]
},
"Sandvik LHD models": {
"SANDVIK LH517i": ["DB 7", "DB 7.6", "DB 8.6", "DB 9.1", "DB 8.4"],
"SANDVIK LH621i": ["DB 8.0", "DB 9.0", "DB 10.7", "DB 11.2"],
"SANDVIK LH515i": ["DB 6.3", "DB 6.8", "DB 7.5"],
"SANDVIK LH514": ["DB 6.2", "DB 7", "DB 5.4"],
"Toro™ LH625iE": ["DB 10"],
"Sandvik LH514E": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7"],
"Toro™ LH514BE": ["DB 4.6", "DB 5", "DB 5.4", "DB 6.2", "DB 7", "DB 7.5"],
"Sandvik LH409E": ["DB 3.8", "DB 4.3", "DB 4.6"]
},
"Epiroc LHD models": {
"Epiroc ST14 SG": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 SG": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"],
"Epiroc ST14": ["DB 4.7", "DB 5", "DB 5.4", "DB 5.8", "DB 6.4", "DB 7.0", "DB 7.8"],
"Epiroc ST18 S": ["DB 9.7", "DB 8.8", "DB 7.9", "DB 7.3", "DB 6.7", "DB 6.3"]
},
"Komatsu LHD models": {
"WX18H": ["DB 8.2", "DB 9.2", "DB 10", "DB 11.2"],
"WX22H": ["DB 10", "DB 11", "DB 12.2", "DB 13.8"]
}
}
class ComboBox(ttk.Combobox):
"""A convenient Combobox."""
def __init__(self, *args, command=None, **kwargs):
self.value = tk.StringVar()
self.value.trace("w", command)
super().__init__(
*args, textvariable=self.value, **kwargs
)
def set_values(self, values):
"""Set values in list."""
self["values"] = values
if values:
self.set(values[0])
def get(self):
"""Return value."""
return self.value.get()
def set(self, value):
"""Set value."""
self.value.set(value)
class Column(tk.Frame):
"""Controls for selecting a loader"""
def __init__(self, *args, command=None, width=30, **kwargs):
super().__init__(*args, **kwargs)
self.command = command
self.group = ComboBox(
self, values=list(models_data), command=self._group_cb, width=width
)
self.model = ComboBox(self, command=self._model_cb, width=width)
self.bucket = ComboBox(self, command=self._bucket_cb, width=width)
self.group.pack(pady=10)
self.model.pack(pady=10)
self.bucket.pack(pady=10)
def _group_cb(self, *_):
"""Group selection changed. Update model dropdown."""
self.model.set_values(list(models_data[self.group.get()]))
def _model_cb(self, *_):
"""Model selection changed. Update bucket dropdown."""
self.bucket.set_values(list(models_data[self.group.get()][self.model.get()]))
def _bucket_cb(self, *_):
"""Bucket selection changed. Execute selection callback command."""
if self.command:
self.command(self.selection())
def selection(self):
"""Return selected manufacturer, model, bucket."""
return self.group.get(), self.model.get(), self.bucket.get()
class Window(tk.Tk):
def __init__(self):
super().__init__()
width = max(len(key) for key in models_data)
for group in models_data:
column = Column(self, command=print, width=width)
column.pack(side=tk.LEFT, padx=10, pady=10)
column.group.set(group)
Window().mainloop()
Posts: 6,804
Threads: 20
Joined: Feb 2020
Aug-28-2023, 01:56 PM
(This post was last modified: Aug-28-2023, 02:01 PM by deanhystad.)
Yes, YOU could do this with CTk combo boxes too. Should be very easy.
|