Calendars are how we tell time, which is why they are needed so often. If you have ever tried to create a calendar, you will know that it’s hard. You need lots of math and weird algorithms to pull it off. Thankfully LVGL has a widget that does all that stuff for us.
Today I will show you some code that creates a LVGL calendar and modifies some of its properties. After the code there is an explanation on how it works.
To get this example to work you will need to add your screen code to the beginning of the code below. If you want more information, you can try How to get a LVGL Micropython screen to work.
Here is the code:
import lvgl
cal = lvgl.calendar(lvgl.scr_act())
cal.set_size(320,240)
cal.set_today_date(2023,1,2)
cal.set_showed_date(2023,1)
lvgl.calendar_header_arrow(cal)
highlight = []
bug_fix = lvgl.calendar_date_t({'year':1,'month':1,'day':1})
highlight.append(bug_fix)
def unhighlight_list(date):
for x in highlight:
if x.year == date.year and x.month == date.month and x.day == date.day:
highlight.remove(x)
return True
return False
def date_clicked(data):
date = lvgl.calendar_date_t()
if not cal.get_pressed_date(date) == lvgl.RES.OK:
return
print(date.year,date.month,date.day)
if not unhighlight_list(date):
highlight.append(date)
cal.set_highlighted_dates(highlight,len(highlight))
cal.add_event_cb(date_clicked,lvgl.EVENT.CLICKED,None)
Understanding This LVGL Code
Ok, now that you have seen all the code, let’s step through each section, so you can understand exactly what each part does. This will make it much easier to actually use calendars in your future projects…
The LVGL Module
Before we can use LVGL we have to import it, so that is the first thing we do.
import lvgl
Creating the Calendar
To begin, we need to create an empty calendar object.
cal = lvgl.calendar(lvgl.scr_act())
Next, we set its size. My screen is 320*240, so setting the calendar’s size to 320*240 makes it fill the entire screen.
cal.set_size(320,240)
Setting the Date
If we left the calendar as is, it would display some random day, so we need to tell it what date to display.
To do this correctly, you need some sort of clock that has the current date, but getting something like that can be a bit of work. Instead, I set the date to the day I created the code.
cal.set_today_date(2023,1,2)
The calendar can only show one month at a time, so we have to set what month is visible. I set it to show the date we created earlier.
cal.set_showed_date(2023,1)
The Header
The default calendar will only show the days of the week. If you want your calendar to show the year and the month there are two options.
First, you could use the dropdown method. This will create two dropdown lists one for the year and one for the month. This code enables the dropdown lists.
lvgl.calendar_header_dropdown(cal)
Second, you could use the arrows method. This way creates a title at the top of the calendar that displays the year and month, then creates two buttons that allow you to move to the next or previous month. The code below will turn arrows on.
lvgl.calendar_header_arrow(cal)
I prefer the arrow method, so it’s the one used in this example.
Highlighting Dates
One feature of Calendars is that you can give it a list of dates to highlight. So we are going to start by creating an empty list to use latter.
highlight = []
Once you tell a Calendar to highlight some dates, you seem to have to always leave at least one date highlighted. The way we can get around this glitch is to highlight a random date that no one will see.
First we have to create an date object with the desired year,month, and day.
bug_fix = lvgl.calendar_date_t({'year':1,'month':1,'day':1})
Then we add it to the list of highlighted dates.
highlight.append(bug_fix)
The Unhighlight Function
To make the code more streamlined we need to create a function that helps us unhighlight a date that we have already highlighted.
We start by creating the new function.
def unhighlight_list(date):
Then we will use a for loop to check if the date we care about is in the highlight list.
for x in highlight:
We will use the if statement below to check the date.
if x.year == date.year and x.month == date.month and x.day == date.day:
If the date is found in the list, we remove it from the list, and then the functions returns True.
highlight.remove(x)
return True
If the date was not in the list, then the function returns False.
return False
The Event Handler
The end goal is that when a date is clicked, it is highlighted, and if you click it again, it will unhighlight. To do all that, we need to create a handler function.
We begin as usual by defining it.
def date_clicked(data):
Next, we are going to create an empty date object.
date = lvgl.calendar_date_t()
This line of code does two things.
First, the if statement checks if a date was clicked.
Second, the get_pressed_date() part sets the date object we created to the clicked date.
if not cal.get_pressed_date(date) == lvgl.RES.OK:
If no date was clicked, the the functions stops running and returns.
return
To make sure everything is working well, the computer prints to the terminal the date that it thinks was clicked.
print(date.year,date.month,date.day)
This code runs the unhighlight function we created on the date that was clicked.
if not unhighlight_list(date):
If the unhighlight function could not find the date we gave it, we will add that date to the highlight list.
The overall effect of these two lines of code is that it toggles whether a date is highlighted or not.
highlight.append(date)
All we have really done up to this point is add and remove dates from a list. Now we need to give that list to the calendar so it can highlight the actual dates.
cal.set_highlighted_dates(highlight,len(highlight))
Connecting the Handler
The last step we need to do is connect the handler we made to the calendar, so whenever a date is clicked the function is called.
cal.add_event_cb(date_clicked,lvgl.EVENT.CLICKED,None)
What Next?
Now that you have seen the code, try running it. You should see a large calendar that displays the date 1/2/2023. Clicking on a date will highlight that date. If you click a highlighted date it will remove the highlight. If you press one of the blue buttons in the corners it will change the visible month.
Calendars by themselves aren’t super useful. A great next step would be hooking up a clock system, so you can tell the real date. You could also experiment with styling to make it look nicer and might add some code that allows you to attach text to certain dates like Christmas or New Years Eve.
If you liked LVGL Calendars another widget that you might also like is the micropython LVGL Tileview.