Reputation: 369
I am using this ttk calendar in my application.
What I want to do is set the calendar using a datetime.date
instance so when the calendar appears the specified date is highlighted.
I thought I could go through the _show_selection
method with manual text
and bbox
args. To test this idea, I placed this line at the end of the __init__
method:
self._show_selection('%02d'%16,(42,61,41,20))
I was hoping it would highlight the 16th of this month (May), but it did not.
I got the args from running print text, bbox
in the _pressed method.
If anyone can shed some light on this, I'd greatly appreciate it.
Upvotes: 8
Views: 603
Reputation: 369
For the most part @Oblivion is correct, however I want to be able to use a Datetime.date
object and to be able to traverse the months and years if needed. Once I changed the set_day
method below everything worked perfectly.
def set_day(self, dt_object):
day = dt_object.day
w = self._calendar
if not w.winfo_viewable():
w.after(200, self.set_day, dt_object)
return
while dt_object.year < self._date.year:
self._prev_month()
while dt_object.year > self._date.year:
self._next_month()
while dt_object.month < self._date.month:
self._prev_month()
while dt_object.month > self._date.month:
self._next_month()
text = '%02d' % day
column = None
for iid in self._items:
rowvals = w.item(iid, 'values')
try:
column = rowvals.index(text)
except ValueError as err:
pass
else:
item = iid
bbox = w.bbox(iid, column)
break
if column is not None:
self._selection = (text, item, column)
self._show_selection(text, bbox)
else:
print "Column is None"
Upvotes: 1
Reputation: 1729
In __setup_selection() there is a binding on the Configure event. Presumably, it's there to remove the "selection canvas" when the calendar is resized. However, the Configure event also fires when the calendar is first mapped to screen, so your pre-selected date disappears before you ever get to see it.
set_day (below) lets you select a day programmatically. It sidesteps the problem of that first Configure event by re-scheduling itself if the widget is not yet visible.
changes to Calendar:
def __setup_selection(self, sel_bg, sel_fg):
self._font = font.Font()
self._canvas = canvas = tkinter.Canvas(self._calendar,
background=sel_bg, borderwidth=0, highlightthickness=0)
canvas.text = canvas.create_text(0, 0, fill=sel_fg, anchor='w')
canvas.bind('<ButtonPress-1>', lambda evt: canvas.place_forget())
#self._calendar.bind('<Configure>', lambda evt: canvas.place_forget())
self._calendar.bind('<Configure>', self.on_configure)
self._calendar.bind('<ButtonPress-1>', self._pressed)
def on_configure(self, event):
self._canvas.place_forget()
if self._selection is not None:
text, iid, column = self._selection
bbox = self._calendar.bbox(iid, column)
self._show_selection(text, bbox)
def _prev_month(self):
"""Updated calendar to show the previous month."""
self._canvas.place_forget()
self._selection = None #
self._date = self._date - self.timedelta(days=1)
self._date = self.datetime(self._date.year, self._date.month, 1)
self._build_calendar() # reconstuct calendar
def _next_month(self):
"""Update calendar to show the next month."""
self._canvas.place_forget()
self._selection = None #
year, month = self._date.year, self._date.month
self._date = self._date + self.timedelta(
days=calendar.monthrange(year, month)[1] + 1)
self._date = self.datetime(self._date.year, self._date.month, 1)
self._build_calendar() # reconstruct calendar
def set_day(self, day):
w = self._calendar
if not w.winfo_viewable():
w.after(200, self.set_day, day)
return
text = '%02d' % day
column = None
for iid in self._items:
rowvals = w.item(iid, 'values')
try:
column = rowvals.index(text)
except ValueError as err:
pass
else:
item = iid
bbox = w.bbox(iid, column)
break
if column is not None:
self._selection = (text, item, column)
self._show_selection(text, bbox)
#test
def test():
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')
ttkcal.set_day(16) #
root.mainloop()
Upvotes: 0