Reputation: 59
I developed this code to use it as a calendar, and at the end, it return the date on a specific format.
from tkinter import*
from tkinter import ttk
from PyQt5.QtCore import QDate, Qt
class Calendar:
def __init__(self):
self.b = 0
def calendar(self):
calendar_window = Tk()
calendar_window.title("Calendar")
calendar_window.geometry("180x300")
calendar_window.resizable(False,False)
Label(calendar_window, text = "DATE") .place(x = 70, y =0)
Label(calendar_window, text = "Month") .place(x = 30, y = 20)
month = StringVar()
month = ttk.Combobox(calendar_window, width = 5, textvariable = month ,
state = "readonly")
month.place(x = 30, y = 40)
month['values'] = ['JAN' ,'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
'AGU', 'SEP', 'OCT', 'NOV', 'DEC']
Label(calendar_window, text = "Year") .place(x = 110, y = 20)
year = StringVar()
year = ttk.Combobox(calendar_window, width = 5, textvariable = year ,
state = "readonly")
year.place(x = 110, y = 40)
year["values"] = ["2015" ,"2016", "2017", "2018", "2019", "2020",
"2021", "2022"]
year.current(0)
day = StringVar()
day_list = []
def radiobutton_creation(event):
days = Frame(calendar_window, width = 180, height = 150)
days.place(x = 3, y = 70)
if month.current() != -1:
d = QDate(int(year.get()), month.current() + 1, 1)
x = [5,30,55,80,105,130,155]
y = [5,35,65,95,125]
i = 1
for ver in y:
for hor in x:
if i <= int(d.daysInMonth()):
b = Radiobutton(days, text =
str(i),variable=day,value= str(i), height = 1, width = 1,indicatoron=0)
b.place(x = hor, y = ver)
day_list.append(b)
i = i + 1
month.bind('<<ComboboxSelected>>', radiobutton_creation)
year.bind('<<ComboboxSelected>>', radiobutton_creation)
Label(calendar_window, text = "HH") .place(x = 55, y =220)
hh = StringVar()
hh = ttk.Combobox(calendar_window, width = 3, textvariable = hh,state =
"readonly")
hh.place(x = 55, y = 240)
hh["values"] = ["00","01" ,"02", "03", "04", "05", "06", "07", "08",
"09", "10","11","12","13","14","15","16","17","18","19","20","21","22","23"]
Label(calendar_window, text = "MM") .place(x = 100, y =220)
mm = StringVar()
mm = ttk.Combobox(calendar_window, width = 3, textvariable = mm,state =
"readonly")
mm.place(x = 100, y = 240)
mm["values"] = ["00","01" ,"02", "03", "04", "05", "06", "07", "08",
"09","10","11","12","13","14","15","16",
"17","18","19","20","21","22","23","24","25"
,"26","27","28","29","30","31","32","33","34"
,"35","36","37","38","39","39","40","42","43"
,"44","45","46","47","48","49","50","51","52"
,"53","54","55","56","57","58","59"]
Label(calendar_window, text = "Z") .place(x = 145, y =240)
def select():
if len(day.get()) < 2:
self.b =
('0'+day.get()+hh.get()+mm.get()+"Z"+month.get()+year.get())
calendar_window.destroy()
else:
self.b =
(day.get()+hh.get()+mm.get()+"Z"+month.get()+year.get())
calendar_window.destroy()
Button(calendar_window, text = "Select", command = select) .place(x =
30, y = 270)
Button(calendar_window, text = "Cancel", command =
calendar_window.destroy) .place(x = 90, y = 270)
calendar_window.update()
calendar_window.mainloop()
return returns()
It works fine, even if a create a new .py file and I code:
from calendar_class import Calendar
print(Calendar().calendar())
Nevertheless when I try to use this with a Label in Tkinter, it doesn`t work:
from tkinter import*
from tkinter import ttk
from calendar_class import Calendar
master = Tk()
master.title("ATO (Air Tasking Order)")
master.geometry('500x500')
def execute():
date = StringVar()
date.set(Calendar().calendar())
Label(master, textvariable = date) .grid(row = 1, column = 1)
Button(master, text = 'Show Date', command = execute) .grid(row = 2, column
= 2)
mainloop()
Or just trying to use print inside a ttk() window it works after the window is closed:
from tkinter import*
from tkinter import ttk
from calendar_class import Calendar
master = Tk()
master.title("ATO (Air Tasking Order)")
master.geometry('500x500')
print(Calendar().calendar())
mainloop()
Upvotes: 0
Views: 54
Reputation: 2554
The issue here is the call to mainloop
in calendar class method. When you call mainloop
function, your code gets stuck there waiting for user events on you GUI. It can only go to next line of code when quit
is called on it, which in your case is called when you close the window.
I would suggest to use calendar_window.update()
in your class method, which will draw your window but will not block your code there. Don't remove the mainloop
call from your main function, otherwise the code will not wait for any user input and end execution instantly.
Refer to this answer for more details about working of mainloop.
UPDATE:
Sorry, I did not try to run your code last time. Assuming you are returning the selected date from Calendar
class, these changes in Calendar
class can solve your problem.
def select():
if len(day.get()) < 2:
self.b = ('0'+day.get()+hh.get()+mm.get()+"Z"+month.get()+year.get())
calendar_window.quit()
else:
self.b = (day.get()+hh.get()+mm.get()+"Z"+month.get()+year.get())
calendar_window.quit()
Button(calendar_window, text = "Select", command = select) .place(x = 30, y = 270)
Button(calendar_window, text = "Cancel", command = calendar_window.quit) .place(x = 90, y = 270)
calendar_window.mainloop()
calendar_window.destroy()
return self.b
So when you call the quit
on button click, it will call destroy
and then go to next call of return
. And you can use your main function as showed in the question and it will work.
And why directly calling destroy
on button click is not working (I guess) is related to use of two Tk()
windows in same application(not suggested). So I would suggest to pass your master
window as argument to Calendar
class and then create Toplevel
window instead of new Tk()
window there. You can read more about Toplevel
window here.
Hope this solves your problem finally.
Upvotes: 1