Get selected date from python wx.lib.calendar

Viewed 1817

How do you make button which open calendar then selects date and closes it? So far I managed just create calendars (I don't get why it always creates 2). But I couldn't figure out how to get selected date. I'm using pythonwx on Python 3.

class MyCalendar(wx.Frame):

    def __init__(self, *args, **kargs):
        wx.Frame.__init__(self, *args, **kargs)
        self.cal = CalendarCtrl(self, 10, wx.DateTime.Now())
        self.timer = wx.Timer(self)



if __name__ == '__main__':  
    app = wx.App()
    frame = MyCalendar(None)
    frame.Show()
    app.MainLoop()

EDIT

adding py3 version

from wx.adv import CalendarCtrl, GenericCalendarCtrl, CalendarDateAttr

class MyCalendar(wx.Frame):

    def __init__(self, *args, **kargs):
        wx.Frame.__init__(self, *args, **kargs)
        self.cal = CalendarCtrl(self, 10, wx.DateTime.Now())
        self.cal.Bind(wx.adv.EVT_CALENDAR, self.OnDate)



    def OnDate(self,event):
        print (self.cal.GetDate())      
        wx.Window.Close(self)
2 Answers
import wx
import wx.adv
class MyCalendar(wx.Frame):

    def __init__(self, *args, **kargs):
        wx.Frame.__init__(self, *args, **kargs)
        self.cal = wx.adv.CalendarCtrl(self, 10, wx.DateTime.Now())
        self.cal.Bind(wx.adv.EVT_CALENDAR, self.OnDate)

    def OnDate(self,event):
        print(self.cal.GetDate())


if __name__ == '__main__':
    app = wx.App()
    frame = MyCalendar(None)
    frame.Show()
    app.MainLoop()

Now double click on a date.

I'll leave you to research creating a frame/panel and putting a button on it, to activate the calendar.

This simple request is a bit more complicated than it first looks, as you have to wait for a result of a date selection, other than now, without over complicating it.
Putting it all in the same class would make life easier, as would using wx.DatePickerCtrl
For what it is worth, here is my attempt at answering your whole question.

import wx
import wx.calendar
import time
class MyCalendar(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "Calendar",size=(300,300))
        self.Panel = wx.Panel(self)
        self.cal = wx.calendar.CalendarCtrl(self.Panel, 10, wx.DateTime.Now())
        self.cal.Bind(wx.calendar.EVT_CALENDAR, self.OnDate)
        self.Show()

    def OnDate(self,event):
        self.Destroy()
        return self.cal.GetDate()

class Myframe(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.Panel = wx.Panel(self)
        self.Button = wx.Button(self.Panel, label="Calendar",size=(60,25),pos=(10,300))
        self.Selected = wx.TextCtrl(self.Panel, -1,"Selected Date",size=(300,25),pos=(10,50))
        self.Button.Bind(wx.EVT_BUTTON, self.ShowCal)
        self.Show()

    def ShowCal(self,event):
        now = wx.DateTime.Now()
        now.SetHMS(0)
        self.Selected_date = MyCalendar(self.Panel)
        while self.Selected_date and self.Selected_date.cal.GetDate() == now:
            wx.Yield()
            time.sleep(0.1)
        try:
            self.Selected.SetValue(str(self.Selected_date.cal.GetDate()))
        except:
            self.Selected.SetValue("Nothing selected")

if __name__ == '__main__':
    app = wx.App()
    frame = Myframe(None)
    app.MainLoop()

I'm sure that there must be a more elegant way of achieving this and hopefully someone else will produce an answer but as you can see I have opted to wait in a while loop until a result other than Now is selected and Now has been adjusted to be midnight, today, as that is what Calendar returns.

Edit: The answer is to use an event, which is fired by the calendar date selection (double clicking on a date)

import wx
import wx.adv
import datetime
import wx.lib.newevent
cal_event, EVT_CAL_EVENT = wx.lib.newevent.NewEvent()

class MyCalendar(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "Calendar",size=(300,300))
        self.parent = parent
        self.Panel = wx.Panel(self)
        self.cal = wx.adv.CalendarCtrl(self.Panel, 10, wx.DateTime.Now())
        self.cal.Bind(wx.adv.EVT_CALENDAR, self.OnDate)
        self.Show()

    def OnDate(self,event):
        evt = cal_event(data=self.cal.GetDate())
        wx.PostEvent(self, evt) #post EVT_CAL_EVENT

class Myframe(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.Panel = wx.Panel(self)
        self.Button = wx.Button(self.Panel, label="Calendar",size=(60,25),pos=(10,300))
        self.Selected = wx.TextCtrl(self.Panel, -1,"Selected Date",size=(300,25),pos=(10,50))
        self.Button.Bind(wx.EVT_BUTTON, self.ShowCal)
        self.Show()

    def ShowCal(self,event):
        now = wx.DateTime.Now()
        now.SetHMS(0)
        self.Selected_date = MyCalendar(self)
        self.Selected_date.Bind(EVT_CAL_EVENT, self.GetCal)

    def GetCal(self,event):
        ymd = map(int, event.data.FormatISODate().split('-'))
        d = datetime.date(*ymd) # Convert to a datetime so we can use standard formatting
        self.Selected.SetValue(d.strftime("%a - %d/%m/%Y"))
        self.Selected_date.Destroy()
        del self.Selected_date

if __name__ == '__main__':
    app = wx.App()
    frame = Myframe(None)
    app.MainLoop()

This provides the date as "Weekday name - dd/mm/yyyy" e.g. Tue - 23/02/2021

Related