【问题标题】:Tkinter window will not close upon clicking a button单击按钮后,Tkinter 窗口不会关闭
【发布时间】:2018-12-31 05:37:03
【问题描述】:

(我为这个幼稚的问题道歉)

我有一个弹出窗口,允许用户选择两个月作为数据收集的起点和终点。

单击“确定”按钮时发生的事件是返回所选范围之间月份的列表和字典,并通知用户所选范围。但是,我也希望在单击“确定”后关闭此窗口。这些事件在callback 函数下。我无法使root.destroy 可访问。

所有涉及的代码都在这里。我的函数callback 是朝向底部的:

from tkinter import *

startDate = 'Dec 16'
now = datetime.now()
endDate = now.strftime('%b %y')
start = datetime.strptime(startDate, '%b %y').date()
end = datetime.strptime(endDate, '%b %y').date()
cur_date = start
range_months = []

while cur_date < end:
    cur_date += relativedelta(months=1)
    range_months.append(cur_date)

range_months = [month.strftime('%b %y') for month in range_months]
dict_months = dict((month, pd.to_datetime(month, format='%b %y')) for month in range_months)

root = Tk()
#root.withdraw()
root.title("Select your Month Range")

# Setting up Grid
mainframe = Frame(root)
mainframe.pack(pady=50, padx=50)
Label(mainframe, text="Select Start Month").grid(row=1, column=1)
Label(mainframe, text="Select End Month").grid(row=1, column=6)

# Creating two Tkinter variables to obtain user input from the drop down menus
tkvar_start = StringVar(root)
tkvar_end = StringVar(root)
tkvar_start.set('Jan 17')  # Setting a default option
tkvar_end.set(endDate)

start_popupMenu = OptionMenu(mainframe, tkvar_start, *dict_months)
end_popupMenu = OptionMenu(mainframe, tkvar_end, *dict_months)
start_popupMenu.grid(row=2, column=1)
end_popupMenu.grid(row=2, column=6)


def callback_range():
    print('The range is from %s to %s' % (tkvar_start.get(), tkvar_end.get()))
    list_of_month_keys = list(dict_months.keys())
    import itertools
    range_dict_months = dict(itertools.islice(dict_months.items(), list_of_month_keys.index(tkvar_start.get()),
                                       list_of_month_keys.index(tkvar_end.get()) + 1))

    return list_of_month_keys, range_dict_months


button = Button(mainframe, text = "OK", command = callback_range)
button.grid(row=3, column=23)

root.mainloop()
list_of_month_keys, range_dict_months = callback_range()

如何在我的函数callback 中使root.destroy() 可访问,同时仍返回list_of_month_keysrange_dict_months,以便在单击“确定”时另外关闭此窗口?

【问题讨论】:

  • 你不能。该函数将在完成 return 语句后停止执行。处理完数据后,您需要重新编写程序以关闭 GUI 窗口。
  • 您的最后一行代码list_of_month_keys, range_dict_months = callback_range() 将永远无法工作。原因是您的函数 callback_range() 在您的 tkinter 主循环中,并且您的最后一行代码将永远无法执行此函数。即使主循环终止了该循环内的所有内容。

标签: python button tkinter


【解决方案1】:

我已经尝试进入你的程序并想出了那个解决方案。

from tkinter import *
import tkinter.messagebox as mb
from datetime import datetime
import itertools
from dateutil.relativedelta import relativedelta
import pandas as pd

class MonthRangeWindow:
    def __init__(self):
        startDate='Dec 16'
        endDate=datetime.now().strftime('%b %y')
        cur_date=start=datetime.strptime(startDate,'%b %y').date()
        end=datetime.strptime(endDate,'%b %y').date()
        range_months=[]
        self.list_of_month_keys,self.range_dict_months=None,None

        while cur_date<end:
            cur_date+=relativedelta(months=1)
            range_months.append(cur_date)

        range_months=[month.strftime('%b %y') for month in range_months]
        self.dict_months=dict((month,pd.to_datetime(month,format='%b %y')) for month in range_months)

        self.root=Tk()
        #self.root.withdraw()
        self.root.title("Select your Month Range")

        mainframe=Frame(self.root)
        mainframe.pack(pady=50,padx=50)

        Label(mainframe,text="Select Start Month").grid(row=1,column=1)
        Label(mainframe,text="Select End Month").grid(row=1,column=6)

        self.tkvar_start=StringVar(root,'Jan 17')
        self.tkvar_end=StringVar(root,endDate)
        start_popupMenu=OptionMenu(mainframe,tkvar_start,*self.dict_months)
        end_popupMenu=OptionMenu(mainframe,tkvar_end,*self.dict_months)
        start_popupMenu.grid(row=2,column=1)
        end_popupMenu.grid(row=2,column=6)

        button=Button(mainframe,text="Ok",command=self.callback_range)
        button.grid(row=3,column=23)

    def callback_range(self):
        mb.showinfo(title='Info',message='The range is from %s to %s.' % (self.tkvar_start.get(),self.tkvar_end.get()),master=self.root)
        self.list_of_month_keys=list(self.dict_months.keys())
        self.range_dict_months=dict(itertools.islice(self.dict_months.items(),self.list_of_month_keys.index(self.tkvar_start.get()),self.list_of_month_keys.index(self.tkvar_end.get()) + 1))

    def mainloop(self,n=0):
        self.root.mainloop(n)
        return self.list_of_month_keys,self.range_dict_months

if __name__=='__main__':
    mrw=MonthRangeWindow()
    list_of_month_keys,range_dict_months=mrw.mainloop()
    print(list_of_month_keys,range_dict_months)

因为我没有那个 pd.to_datetime(...) 的 pandas 模块,而且我懒得下载它,所以无法测试它。但我认为您应该能够在需要时对其进行调试。

我还允许自己从 tkinters 消息框模块插入一个信息窗口,而不是 print。如果您不想要这个,只需再次打印替换它。

【讨论】:

    【解决方案2】:

    您可能希望将多个命令绑定到按钮。

    def combined_functions(*funcs):
        def combined_func(*args, **kwargs):
            for f in funcs:
                f(*args, **kwargs)
        return combined_func
    
    //close the mainframe
    def close_window():
        mainframe.quit()
    
    button = Button(mainframe, text = "OK", command = combined_functions(callback_range, close_window))
    

    此外,在方法的中间导入模块可能不是一个好主意。如果将range_dict_months 拆分为单独的行,代码看起来会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 2023-02-17
      • 2013-01-17
      • 2016-06-16
      相关资源
      最近更新 更多