Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a <ComboboxSelected> virtual event with tkinter

I am using a tkk.Combobox themed widget in Python 3.5.2. I want an action to happen when a value is selected.

In the Python docs, it says:

The combobox widgets generates a <<ComboboxSelected>> virtual event when the user selects an element from the list of values.

Here on the Stack, there are a number of answers (1, 2, etc) that show how to bind the event:

cbox.bind("<<ComboboxSelected>>", function)

However, I can't make it work. Here's a very simple example demonstrating my non-functioning attempt:

import tkinter as tk
from tkinter import ttk

tkwindow = tk.Tk()

cbox = ttk.Combobox(tkwindow, values=[1,2,3], state='readonly')
cbox.grid(column=0, row=0)

cbox.bind("<<ComboboxSelected>>", print("Selected!"))

tkwindow.mainloop()

I get one instance of "Selected!" immediately when I run this code, even without clicking anything. But nothing happens when I actually select something in the combobox.

I'm using IDLE in Windows 7, in case it makes a difference.

What am I missing?

like image 373
bitsmack Avatar asked Nov 16 '16 19:11

bitsmack


People also ask

How to use a Combobox in Tkinter?

Use ttk. Combobox(root, textvariable) to create a combobox. Set the state property to readonly to prevent users from entering custom values. A combobox widget emits the '<<ComboboxSelected>>' event when the selected value changes.

What is tkinter TTK?

ttk is a module that is used to style the tkinter widgets. Just like CSS is used to style an HTML element, we use tkinter. ttk to style tkinter widgets.

How do you make a Combobox not editable in Python?

We can select any option in the dropdown list. Now add state = "readonly" in the Combobox object, it will make the Combobox Entry Widget disabled.


2 Answers

The problem is not with the event <<ComboboxSelected>>, but the fact that bind function requires a callback as second argument.

When you do:

cbox.bind("<<ComboboxSelected>>", print("Selected!"))

you're basically assigning the result of the call to print("Selected!") as callback.

To solve your problem, you can either simply assign a function object to call whenever the event occurs (option 1, which is the advisable one) or use lambda functions (option 2).

Here's the option 1:

import tkinter as tk
from tkinter import ttk

tkwindow = tk.Tk()

cbox = ttk.Combobox(tkwindow, values=[1,2,3], state='readonly')
cbox.grid(column=0, row=0)


def callback(eventObject):
    print(eventObject)

cbox.bind("<<ComboboxSelected>>", callback)

tkwindow.mainloop()

Note the absence of () after callback in: cbox.bind("<<ComboboxSelected>>", callback).

Here's option 2:

import tkinter as tk
from tkinter import ttk

tkwindow = tk.Tk()

cbox = ttk.Combobox(tkwindow, values=[1,2,3], state='readonly')
cbox.grid(column=0, row=0)

cbox.bind("<<ComboboxSelected>>", lambda _ : print("Selected!"))

tkwindow.mainloop()

Check what are lambda functions and how to use them!

Check this article to know more about events and bindings:

http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

like image 98
nbro Avatar answered Sep 20 '22 21:09

nbro


Thanks you for the posts. I tried *args and it workes with bind and button as well:

import tkinter as tk
from tkinter import ttk
tkwindow = tk.Tk()
cbox = ttk.Combobox(tkwindow, values=[1,2,3], state='readonly')

def callback(*args):
    print(eventObject)

cbox.bind("<<ComboboxSelected>>", callback)
btn = ttk.Button(tkwindow, text="Call Callback", command=callback);

tkwindow.mainloop()
like image 21
daRich Avatar answered Sep 20 '22 21:09

daRich