Andres
Andres

Reputation: 59

print statement from an import class works once the TTK windows is closed

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

Answers (1)

Kamal
Kamal

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

Related Questions