2016-05-11 11 views
6

Ich verwende this ttk calendar in meiner Anwendung.Wie programmierbarer TTK-Kalender

Ich möchte den Kalender mit einer datetime.date Instanz festlegen. Wenn der Kalender angezeigt wird, wird das angegebene Datum hervorgehoben.

Ich dachte, ich könnte durch die _show_selection Methode mit manuellen text und bbox Args gehen. Um diese Idee zu testen, stellte ich diese Zeile am Ende des __init__ Methode:

self._show_selection('%02d'%16,(42,61,41,20))

Ich hatte gehofft, es würde den 16. dieses Monats (Mai) markieren, aber es kam nicht.

Ich habe die Argumente von print text, bbox in der _pressed-Methode ausgeführt.

Wenn jemand etwas Licht darauf werfen kann, würde ich es sehr schätzen.

+1

Ich bin auch verwirrt. Ich habe 'print ((text, textw, bbox, leinwand ['background'], x, y, leinwand ['breite'], leinwand ['höhe'], leinwand.text), '\ n', (self._calendar, canvas.coords (canvas.text), canvas.itemcget (canvas.text, 'text'))) 'am Ende von _show_selection und alles ist gleich. Ich fügte auch 'self._selection = ('16', 'I004', '# 2')' vor dem hinzugefügten Anruf in '__init__' hinzu, um der Zeile in' _pressed' zu entsprechen. Ich habe sogar 'self._canvas.place_forget() hinzugefügt, indem ich in _setup_selection nachgesehen habe. –

+1

Ich versuche auch 'self._canvas.event_generate ('', x = 50, y = 73) self._calendar.event_generate ('', x = 50, y = 73) '. Ich setze 'print (evt.x, evt.y, evt.widget)' am Anfang von '_pressed', um zu überprüfen, dass es beim Start mit im Wesentlichen demselben Ereignis aufgerufen wird. Funktioniert immer noch nicht. –

Antwort

0

In __setup_selection() gibt es eine Bindung für das Configure-Ereignis. Vermutlich ist es da, um den "Auswahlbereich" zu entfernen, wenn der Kalender in der Größe geändert wird. Das Configure-Ereignis wird jedoch auch ausgelöst, wenn der Kalender zum ersten Mal dem Bildschirm zugeordnet wird, sodass das zuvor ausgewählte Datum verschwindet, bevor Sie es jemals sehen .

set_day (unten) können Sie einen Tag programmgesteuert auswählen. Es vermeidet das Problem des ersten Configure-Ereignisses, indem es sich neu einplant, wenn das Widget noch nicht sichtbar ist.

Änderungen Kalender:

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() 
0

Zum größten Teil @Oblivion ist richtig, jedoch mag ich in der Lage sein, zu verwenden, um ein Objekt Datetime.date und in der Lage sein, die Monate und Jahre zu durchqueren, wenn nötig. Sobald ich die set_day Methode unten geändert habe, hat alles perfekt funktioniert.

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"