Tao Zeng
Tao Zeng

Reputation: 39

ttk combobox selection synchronize the state of entry

I would like to realize a special case, when i select the value in combobox, the entry state changes correspondingly, e.g. when i select 1 in levels, the entry of level-1 is active, while the entry of level-2 is disabled, can anyone give me some suggestion. when i select 2 in levels, both of the state of entry are enabled.

# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk



class MainGui(tk.Tk):

    def __init__(self):

        super().__init__()
        self.create_widgets()

    def create_widgets(self):

        label_1 = tk.Label(self,
                  text = "Levels:",
                  anchor = 'w')
        label_1.grid(row=0, column=0)

        ComboBox1 = ttk.Combobox(self, width = 10, state = 'readonly')
        ComboBox1["values"] = ("1", "2")
        ComboBox1.current(0)
        ComboBox1.grid(row=0, column=1)

        label1 = tk.Label(self,
                  text = "Level-1:",
                  anchor = 'w')
        label1.grid(row=1, column=0)

        entry1 = tk.Entry(self,
                      width = 10,
                      )
        entry1.grid(row=1, column=1)

        label2 = tk.Label(self,
                  text = "Level-2:",
                  anchor = 'w')
        label2.grid(row=2, column=0)

        entry2 = tk.Entry(self,
                      width = 10,
                      )
        entry2.grid(row=2, column=1)


def main():

    # gui
    root = MainGui()
    root.mainloop()


if __name__ == '__main__':
    main()

Upvotes: 0

Views: 82

Answers (2)

Matiiss
Matiiss

Reputation: 6156

Here is a solution (sample):

from tkinter import Tk, Label, Entry, Frame
from tkinter.ttk import Combobox


entry_list = []


def activate_entries(event=None):
    to = int(combobox.get())
    for entry in entry_list[:to]:
        entry.config(state='normal')
    for entry in entry_list[to:]:
        entry.config(state='disabled')


root = Tk()

values = []
for i in range(5):
    (frame := Frame(root)).grid(row=i + 1, column=0)
    Label(frame, text=f'Level-{i + 1}').pack()
    (e := Entry(frame, state='disabled' if i != 0 else 'normal',
                disabledbackground='grey80')).pack()
    entry_list.append(e)
    values.append(i + 1)

combobox = Combobox(root, values=values, state='readonly')
combobox.current(0)
combobox.grid(row=0, column=0)

combobox.bind('<<ComboboxSelected>>', activate_entries)

root.mainloop()

The main part here is the activate_entries() function, it simply gets the value from combobox and uses a list of the entries to set their state based on their index in the list which is given by the combobox. (Also some parts require a Python version of 3.8 or higher, can be adjusted for older versions too), also note the <<ComboboxSelected>> event that calls the activate_entries() function when user selects something from the combobox.

EDIT: added disabledbackground='grey80' to visually indicate that the entry is disabled

EDIT2: you can obviously set the range to two which will create two entries, their reference is saved in the entry_list so you can access them through that list to get their value for example

Upvotes: 1

acw1668
acw1668

Reputation: 46669

You can bind the virtual event <<ComboboxSelected>> on ComboBox1 and update the state of Entry2 in the event callback which will be executed whenever the selection of ComboBox1 is changed. But you need to change ComboBox1 and entry2 to instance variables in order to access them inside the event callback:

def create_widgets(self):
    ...
    # changed ComboBox1 to instance variable self.ComboBox1
    self.ComboBox1 = ttk.Combobox(self, width = 10, state = 'readonly')
    self.ComboBox1["values"] = ("1", "2")
    self.ComboBox1.current(0)
    self.ComboBox1.grid(row=0, column=1)
    self.ComboBox1.bind("<<ComboboxSelected>>", self.on_select)
    ...
    # changed entry2 to instance variable self.entry2
    self.entry2 = tk.Entry(self,
                          width = 10,
                          state = "disabled"  # initially disabled
                          )
    self.entry2.grid(row=2, column=1)

def on_select(self, event=None):
    # set state of entry2 based on selected value
    self.entry2.config(state="normal" if self.ComboBox1.get()=="2" else "disabled")

Upvotes: 1

Related Questions