You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter应用Toplevel窗口不显示且跨类调用选择变量时触发AttributeError问题求助

Tkinter应用Toplevel窗口不显示且跨类调用选择变量时触发AttributeError问题求助

我仔细看了你的代码和遇到的两个问题:一是跨类调用选中的月份/年份时触发AttributeError,二是Toplevel选择窗口压根不显示。咱们一步步拆解解决:

一、解决AttributeError: 'InputWindow' object has no attribute 'selected_month'问题

这个错误的核心原因很直白:你在用户还没点击「Confirm」按钮的时候,就去读取selected_month和selected_year了。

看你的代码流程:

  1. 在App的__init__里调用open_input_window()
  2. open_input_window()刚创建完InputWindow,立刻就调用handle_input_window_selections()
  3. 这时候用户还没操作下拉框,更没点确认,InputWindow里的selected_month和selected_year根本还没被赋值,自然会报错。

解决方案:用回调函数传递选中值

我们需要等用户点击「Confirm」后,再把选中的值传递给App,而不是主动去读。修改步骤如下:

  1. 修改InputWindow类,让它接收一个回调函数,在用户确认后调用这个函数传递选中值:
class InputWindow(tk.Toplevel):
    def __init__(self, parent, on_confirm):
        super().__init__(parent)
        self.on_confirm = on_confirm  # 保存回调函数
        self.title("Schedule Selection")
        self.geometry("400x500")
        
        # 原有的月份、年份选择控件代码不变...

    def confirm_selections(self):
        if self.selections_are_valid():
            self.selected_month = self.select_schedule_month.get()
            self.selected_year = self.select_schedule_year.get()
            self.withdraw()
            self.master.deiconify()
            self.on_confirm(self.selected_month, self.selected_year)  # 调用回调,传递选中值
  1. 修改App的open_input_window方法,把handle_input_window_selections作为回调传给InputWindow,去掉立刻调用的代码:
def open_input_window(self):
    self.input_window = InputWindow(self, self.handle_input_window_selections)
    # 删掉原来的 self.handle_input_window_selections() 调用
  1. 调整handle_input_window_selections方法,直接接收选中的月份和年份,然后更新TitleFrame的标签:
def handle_input_window_selections(self, selected_month, selected_year):
    print(selected_month, selected_year)    
    # 调用TitleFrame的方法更新标签
    self.title_frame.update_calendar_labels(selected_month, selected_year)
  1. 给TitleFrame添加更新标签的方法,让它能动态修改月份和年份的显示:
class TitleFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.config(borderwidth=1, relief="raised", width=1300)
        self.grid(column=0, row=0, columnspan=35, padx=10, pady=10)
        
        # 原有的其他控件代码不变...
        
        self.Calendar_Month_label = tk.Label(self, text="Selected Month", font=("Calibri", 12))
        self.Calendar_Month_label.grid(column=0, row=2)
        self.Calendar_Year_label = tk.Label(self, text="Selected year", font=("Calibri", 12))
        self.Calendar_Year_label.grid(column=0, row=3)
    
    def update_calendar_labels(self, month, year):
        # 修改标签文本为选中的月份和年份
        self.Calendar_Month_label.config(text=f"Selected Month: {month}")
        self.Calendar_Year_label.config(text=f"Selected Year: {year}")

二、解决Toplevel窗口不显示的问题

你的代码最后有一行app.withdraw(),而且App的__init__里是先创建InputWindow再处理主窗口,这可能导致窗口显示逻辑混乱。调整如下:

  1. 修改App的__init__方法,先隐藏主窗口,再创建InputWindow:
class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Schedule Window")
        self.geometry("1300x300")
        self.withdraw()  # 先隐藏主窗口,等用户确认后再显示
        self.open_input_window()

        # 原有的title_frame创建代码不变...
  1. 删掉代码最后一行的app.withdraw():
app = App()
# app.withdraw()  # 把这行删掉
app.mainloop()

这样调整后,程序启动时会直接显示InputWindow选择窗口,用户点击确认后,主窗口才会显示,同时选中的月份和年份也会正确更新到TitleFrame里。

另外,注意你原来的handle_input_window_selections里重新创建了TitleFrame,这会导致原来的控件被覆盖,咱们上面的方案是直接更新现有TitleFrame的标签,避免重复创建。

备注:内容来源于stack exchange,提问作者Blue4Life90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 12:53:16