оператор print из класса импорта работает после закрытия окон TTK - PullRequest
0 голосов
/ 01 ноября 2018

Я разработал этот код, чтобы использовать его в качестве календаря, и в конце он возвращает дату в определенном формате.

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

Работает нормально, даже если создаешь новый .py файл и я кодирую:

from calendar_class import Calendar
print(Calendar().calendar())

Тем не менее, когда я пытаюсь использовать это с меткой в ​​Tkinter, это не работает:

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

Или просто пытаетесь использовать print внутри окна ttk (), оно работает после закрытия окна:

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

1 Ответ

0 голосов
/ 01 ноября 2018

Проблема здесь заключается в вызове mainloop в методе класса календаря. Когда вы вызываете функцию mainloop, ваш код застревает там, ожидая пользовательских событий в вашем графическом интерфейсе. Переход к следующей строке кода возможен только при вызове quit, который в вашем случае вызывается при закрытии окна.

Я бы предложил использовать calendar_window.update() в вашем методе класса, который будет рисовать ваше окно, но не будет блокировать ваш код там. Не удаляйте вызов mainloop из своей основной функции, иначе код не будет ожидать ввода данных пользователем и немедленно завершит выполнение.

Обратитесь к этому ответу для более подробной информации о работе mainloop.

UPDATE:

Извините, я не пытался запустить ваш код в прошлый раз. Предполагая, что вы возвращаете выбранную дату из класса Calendar, эти изменения в классе Calendar могут решить вашу проблему.

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

Поэтому, когда вы вызываете quit при нажатии кнопки, он будет вызывать destroy, а затем перейдет к следующему вызову return. И вы можете использовать свою основную функцию, как показано в вопросе, и она будет работать.

И почему прямой вызов destroy при нажатии кнопки не работает (я полагаю) связан с использованием двух окон Tk() в одном приложении (не рекомендуется). Поэтому я бы предложил передать ваше master окно в качестве аргумента классу Calendar и затем создать Toplevel окно вместо нового окна Tk(). Подробнее о Toplevel окне можно прочитать здесь .

Надеюсь, это наконец решит вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...