1

I am facing an issue where when I want to select a date from a tkCalendar using DateEntry but the the Calendar goes out of screen. Image showing Calendar goes out of screen

I saw a few solutions which I have added the link to below.

  1. Tkcalendar: Right align calendar dropdown with the DateEntry
  2. Behaviour of DateEntry in Tkinter Window

They suggest to rewrite the drop_down function to automatically align the calendar. When I use that, the get_date() function does not work and gives the following error.

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\rmijagir\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "D:/task_tracking/scripts/temp.py", line 49, in <lambda>
    Button(root,text='Analyse',command=lambda: print(date1.get_date())).grid(column=0)
AttributeError: 'NoneType' object has no attribute 'get_date'

I want to retrieve the selected date and store it in a variable as well as display the entire Calendar on the screen.

My Code is as follows:

from tkcalendar import DateEntry
from datetime import timedelta
import tkinter as tk
from tkinter import *

class MyDateEntry(DateEntry):
    def __init__(self, master=None, align='left', **kw):
        DateEntry.__init__(self, master, **kw)
        self.align = align

    def drop_down(self):
        """Display or withdraw the drop-down calendar depending on its current state."""
        if self._calendar.winfo_ismapped():
            self._top_cal.withdraw()
        else:
            self._validate_date()
            date = self.parse_date(self.get())
            h = self._top_cal.winfo_reqheight()
            w = self._top_cal.winfo_reqwidth()
            x_max = self.winfo_screenwidth()
            y_max = self.winfo_screenheight()
            # default: left-aligned drop-down below the entry
            x = self.winfo_rootx()
            y = self.winfo_rooty() + self.winfo_height()
            if x + w > x_max:  # the drop-down goes out of the screen
                # right-align the drop-down
                x += self.winfo_width() - w
            if y + h > y_max:  # the drop-down goes out of the screen
                # bottom-align the drop-down
                y -= self.winfo_height() + h
            if self.winfo_toplevel().attributes('-topmost'):
                self._top_cal.attributes('-topmost', True)
            else:
                self._top_cal.attributes('-topmost', False)
            self._top_cal.geometry('+%i+%i' % (x, y))
            self._top_cal.deiconify()
            self._calendar.focus_set()
            self._calendar.selection_set(date)




root = tk.Tk()

tk.Label(root, text='left align').grid(row=0, column=0)
tk.Label(root, text='right align').grid(row=0, column=1)
date1=MyDateEntry(root).grid(row=1, column=0)
date2=MyDateEntry(root, align='right').grid(row=1, column=1)
Button(root,text='Analyse',command=lambda: print(date1.get_date())).grid(column=0)
root.mainloop() 
Ruchi M
  • 11
  • 1
  • Does this answer your question? [Tkinter: AttributeError: NoneType object has no attribute ](https://stackoverflow.com/questions/1101750/tkinter-attributeerror-nonetype-object-has-no-attribute-attribute-name) – Thingamabobs Jun 16 '22 at 10:19
  • I tried that, but I am still getting the same error. I replaced the "Button(root,text='Analyse',command=lambda: print(date1.get_date())).grid(column=0)" and split it into `btn=Button(root,text='Analyse',command=lambda: print(date1.get_date())) btn.grid(column=0)' – Ruchi M Jun 16 '22 at 10:48
  • Did you separate all construction from their geometry methods? Because `date1.get_date()` will throw this error as long as date1 is not changed as suggested. You have to understand that the geometry methods like `grid` return `None` while the constructor will return a **reference** to your object with that you can address this object. – Thingamabobs Jun 16 '22 at 10:53
  • Yes that worked! I had to separate all the commands having .grid() (date1, date2, and Button). Thanks! If you could add this as a solution I can mark it as the answer. – Ruchi M Jun 16 '22 at 10:58
  • I'm glad I could help you, but I rather would have to mark your question as duplicated since there are already excellent answers to this topic. – Thingamabobs Jun 16 '22 at 11:04
  • Replace this date1=tk.Entry(root).grid(row=1, column=0) date2=tk.Entry(root, align='right').grid(row=1, column=1) I understand align. – toyota Supra Jun 17 '22 at 12:30
  • Your code is very garbage. But what is this? command=lambda: print(date1.get_date())) – toyota Supra Jun 17 '22 at 12:31

0 Answers0