How do I use binding with ttkbootstrap.DateEntry to update a Label with the selected date?

467 Views Asked by At

I'm using the ttkbootstrap framework mainly because of the modern DateEntry, and it has some useful themes. My goal is to have a DateEntry widget automatically update a Label with the date selected from the DatePickerPopup, but the "<<DateEntrySelected>>" event using .bind() does not work like it does with regular tkinter. My work-around is to use a Button to call my update_label function on-click. What is the virtual event that is generated each time the user selects a date?

Here's my code snippet:

import ttkbootstrap as ttk
from datetime import datetime


def update_label(event):
    selected_date = cal.entry.get()
    date_object = datetime.strptime(selected_date, "%m/%d/%Y")
    formated_date = date_object.strftime("%A, %b %d")
    label.config(text=f"{formated_date}")


root = ttk.Window()
root.geometry("600x400")

# Label
label = ttk.Label(root, text="Today")
label.pack(pady=5)

# DateEntry
cal = ttk.DateEntry(root, bootstyle="primary")
cal.pack(pady=5)
cal.bind("<<DateEntrySelected>>", update_label)  # FIX

root.mainloop()

ttkbootstrap docs: https://ttkbootstrap.readthedocs.io/en/latest/api/widgets/dateentry/

There, it says... "A date entry widget combines the Combobox and a Button with a callback attached to the get_date function. When pressed, a date chooser popup is displayed. The returned value is inserted into the combobox. The date chooser popup will use the date in the combobox as the date of focus..."

The workaround is to use a Button, like so...

btn = ttk.Button(root, text="Update", command=update_label)
btn.pack(pady=5)
3

There are 3 best solutions below

0
On BEST ANSWER

You can use StringVar and bind it to calendar.entry:

from datetime import datetime
from tkinter import StringVar

import ttkbootstrap as ttk


def update_label(sv):
    selected_date = sv.get()
    if selected_date == "":
        return
    date_object = datetime.strptime(selected_date, "%m/%d/%Y")
    formated_date = date_object.strftime("%A, %b %d")
    label.config(text=f"{formated_date}")


root = ttk.Window()
root.geometry("600x400")

# Label
label = ttk.Label(root, text="Today")
label.pack(pady=5)

# DateEntry
cal = ttk.DateEntry(root, bootstyle="primary")
cal.pack(pady=5)

sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: update_label(sv))
cal.entry.configure(textvariable=sv)


root.mainloop()

Creates this app:

enter image description here

0
On

ttkbootstrap.DateEntry does not generate the virtual event <<DateEntrySelected>>. However you can create a custom DateEntry class to simulate the feature:

...

class MyDateEntry(ttk.DateEntry):
    # override function 
    def _on_date_ask(self):
        super()._on_date_ask()
        # generate the virtual event
        self.event_generate("<<DateEntrySelected>>")

    # function to return the selected date
    def get_date(self):
        return datetime.strptime(self.entry.get(), self._dateformat)

def update_label(event):
    date_object = event.widget.get_date()
    formated_date = date_object.strftime("%A, %b %d")
    label.config(text=f"{formated_date}")

...

# use the custom DateEntry
cal = MyDateEntry(root, bootstyle="primary")
...
0
On

My work-around is to use a Button to call my update_label function on-click.

The problem can be fix.

Remove the parameter in update_label function.

Comment out on line 7 and 8.

Add Button widget.

Snippet:

def update_label():
    selected_date = cal.entry.get()
    #date_object = datetime.strptime(selected_date, "%m/%d/%Y")
    #formated_date = date_object.strftime("%A, %b %d")
    label.config(text=f"{selected_date}")

...
...
...
btn = ttk.Button(root, text="Update", command=update_label)
btn.pack(pady=5)

Screenshot:

enter image description here