Python Forum
CTkComboBox - not working - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: CTkComboBox - not working (/thread-40617.html)

Pages: 1 2


CTkComboBox - not working - Sedos101 - Aug-27-2023

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!


RE: CTkComboBox - not working - menator01 - Aug-27-2023

Please use bb tags when posting. It helps with the formatting.


RE: CTkComboBox - not working - Sedos101 - Aug-27-2023

[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!


RE: CTkComboBox - not working - Sedos101 - Aug-27-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


RE: CTkComboBox - not working - deanhystad - Aug-27-2023

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()



RE: CTkComboBox - not working - Sedos101 - Aug-27-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?


RE: CTkComboBox - not working - deanhystad - Aug-27-2023

See above.

And please post runnable examples that demonstrate the problem.


RE: CTkComboBox - not working - Sedos101 - Aug-28-2023

(Aug-27-2023, 02:04 PM)deanhystad Wrote: See above.

And please post runnable examples that demonstrate the problem.

THANK YOU SOO MUCH!!


RE: CTkComboBox - not working - Sedos101 - Aug-28-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()



RE: CTkComboBox - not working - deanhystad - Aug-28-2023

Yes, YOU could do this with CTk combo boxes too. Should be very easy.