Inner Peace Inner Peace - 4 years ago 288
Python Question

python calendar widget - return the user-selected date

This ttk calendar class makes a calendar based on tkinter. How do make it return the value of the selected date? Below is what I tried, it returned 'NoneType object is not callable':

def test():
import sys
root = Tkinter.Tk()
root.title('Ttk Calendar')
ttkcal = Calendar(firstweekday=calendar.SUNDAY)
ttkcal.pack(expand=1, fill='both')

x = ttkcal.selection() #this and the following line are what i inserted
print 'x is: ', x #or perhaps return x

if 'win' not in sys.platform:
style = ttk.Style()
style.theme_use('clam')
root.mainloop()

if __name__ == '__main__':
test()

Answer Source

Selection is a @property, so you need to the following to have your code exectued:

x = ttkcal.selection

Also, using this calendar, you can get the selected date, after you close the callendar widget (i.e. after mainloop()). Thus your code should be:

def test2():
    import sys
    root = Tkinter.Tk()
    root.title('Ttk Calendar')
    ttkcal = Calendar(firstweekday=calendar.SUNDAY)
    ttkcal.pack(expand=1, fill='both')

    if 'win' not in sys.platform:
        style = ttk.Style()
        style.theme_use('clam')

    root.mainloop()

    x = ttkcal.selection    
    print 'x is: ', x  

Just in case. If you dont want to close the calendar window to get the selected value, but you want to get them "live" as they are clicked, to e.g. display them in other window's label, you can do the following:

First extend the Calendar class to add the callback function that will be called each time you select some date:

class Calendar2(Calendar):
    def __init__(self, master=None, call_on_select=None, **kw):
        Calendar.__init__(self, master, **kw)
        self.set_selection_callbeck(call_on_select)

    def set_selection_callbeck(self, a_fun):
         self.call_on_select = a_fun


    def _pressed(self, evt):
        Calendar._pressed(self, evt)
        x = self.selection
        #print(x)
        if self.call_on_select:
            self.call_on_select(x)

With this, you can make the new test2 example, which has two windows. One for Calendar, and one window with some label (for instance):

class SecondFrame(Tkinter.Frame):

    def __init__(self, *args, **kwargs):
        Tkinter.Frame.__init__(self, *args, **kwargs)
        self.l = Tkinter.Label(self, text="Selected date")
        self.l.pack()
        self.pack()

    def update_lable(self, x):
        self.l['text'] = x;



def test2():
    import sys
    root = Tkinter.Tk()
    root.title('Ttk Calendar')


    ttkcal = Calendar2(firstweekday=calendar.SUNDAY)
    ttkcal.pack(expand=1, fill='both')

    if 'win' not in sys.platform:
        style = ttk.Style()
        style.theme_use('clam')           


    sf = SecondFrame(Tkinter.Toplevel())

    ttkcal.set_selection_callbeck(sf.update_lable)        

    root.mainloop()

In this example, the label in SecondFrame, will be updated each time you select some date in the calendar.

enter image description here

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download