Tkinter 应用程序 - 我的顶级窗口未出现。应用程序卡在主循环中

问题描述 投票:0回答:1

我正在尝试构建一个工作计划跟踪器,从标题开始。图片附件显示了设计完成后的外观

Schedule Header Cosmetics

到目前为止我已经上了三堂课,

  • InputWindow:一个顶级窗口,供用户从两个组合框中选择月份和年份
  • App:主窗口,根据InputWindow中的用户选择,App应该加载由容器TitleFrame中的元素组成的标题
  • TitleFrame:由应用程序标题、左侧所选月份和所选年份组成的框架,以及由第一行该月的工作日、第二行该月的天数和人员班次组成的网格,如“第三行上有 D”或“N”。

这是代码:

# PEP8 Compliant Guidance
# Standard Library Imports
import tkinter as tk
from tkinter import ttk
import datetime

# Third-Party Library Imports

# Local Application/Library Specific Imports
import functions

class InputWindow(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        # Customize the top-level window as needed
        self.title("Schedule Selection")
        self.geometry("400x500")
        
        # widgets, labels, and other elements for user selections
        currentdate = datetime.datetime.now()
        currentmonth = currentdate.strftime("%B")
        currentyear = currentdate.strftime("%Y")
        
        # Month Selection
        self.select_schedule_month = ttk.Combobox(self, values=functions.months_list())
        self.select_schedule_month.set(currentmonth)
        self.select_schedule_month.pack()
        
        # Year Selection
        self.select_schedule_year = ttk.Combobox(self, values=functions.years_list())
        self.select_schedule_year.set(currentyear)
        self.select_schedule_year.pack()
        
        # Button to confirm selections and open the main application window
        sel_button = tk.Button(self, text="Confirm", command=self.confirm_selections)
        sel_button.pack()

    def confirm_selections(self):
        # Perform validation and check if the proper selections are made
        # If selections are valid, hide the top-level window and open the main application window
        if self.selections_are_valid():
            self.selected_month = self.select_schedule_month.get()
            self.selected_year = self.select_schedule_year.get()
            self.withdraw()  # Hide the top-level window
            self.master.deiconify()  # Show the main application window

    def selections_are_valid(self):
        # Implement your logic to validate selections
        # Return True if selections are valid, False otherwise
        return True

# The Main App Window - 35 columns | 5 rows
class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Schedule Window")
        self.geometry("1300x300")
        self.open_input_window()

        # title frame
        self.title_frame = TitleFrame(self)
        self.title_frame.grid(column=0, row=0, columnspan=35, padx=10, pady=10)
        
    def open_input_window(self):
        self.input_window = InputWindow(self)
        # self.wait_window(self.input_window)  # Wait for the top-level window to close
        self.handle_input_window_selections()
        
    def handle_input_window_selections(self):
        if self.input_window is not None:
            selected_month = self.input_window.selected_month
            selected_year = self.input_window.selected_year
            
            # Use the selected month and year to perform any necessary operations
            print(selected_month, selected_year)    
        
        # title frame
        self.title_frame = TitleFrame(self)
        self.title_frame.grid(column=0, row=0, columnspan=35, padx=10, pady=10)
    
    
# Schedule Header: Includes - Title, Calendar, Shifts, Crew Name, and Crew ID
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.title_label = tk.Label(self, text="Overtime Schedule", font=("Calibri", 22))
        self.title_label.config(padx=462)
        self.title_label.grid(column=0, row=0, columnspan=24, sticky="w")
        
        self.ID_detection_label = tk.Label(self, text=f"Current User: {functions.get_user_id()}", 
                                           font=("Calibri", 12))
        # self.ID_detection_label.config(bg="black", fg="white")
        self.ID_detection_label.grid(column=34, row=0, sticky="e")
        
        self.Calendar_Month_hdr = tk.Label(self, text="Schedule Calendar", font=("Calibri", 12))
        self.Calendar_Month_hdr.grid(column=0, row=1)
        # self.Calendar_Month_hdr.configure(bg="black", fg="white")
        
        """Need to add a calendar widget for this feature"""
        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)
        
# Top Level Selector
class SelectorFrame(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        pass

app = App()

app.withdraw()  # Hide the main application window

app.mainloop()

最初应用程序运行良好,直到我尝试从 InputWindow 中的组合框选择创建变量并在 TitleFrame 中使用它们作为标签。我对 python 和 tkinter 很陌生,想在尝试更新类标签之前尝试从另一个类调用变量。

InputWindow 第 42 和 43 行 - 初始分配

            self.selected_month = self.select_schedule_month.get()
            self.selected_year = self.select_schedule_year.get()

调用App Line 71-75打印在InputWindow中选择的值

    def handle_input_window_selections(self):
        if self.input_window is not None:
            selected_month = self.input_window.selected_month
            selected_year = self.input_window.selected_year
            
            # Use the selected month and year to perform any necessary operations
            print(selected_month, selected_year)    

测试时所有本地导入功能均按预期工作

我在尝试调用 selected_month/selected_year 变量时看到的错误是 AttributeError。我不确定如何从课堂外调用选择,因此我需要对此进行一些教育,但即使从方程中删除这些变量,我仍然无法显示顶级窗口。

Exception has occurred: AttributeError
'InputWindow' object has no attribute 'selected_month'
  File "C:\Users\edit\OneDrive\Py Scripts\Tkinter GUI\Schedule App\Schedule_GUI.py", line 71, in handle_input_window_selections
    selected_month = self.input_window.selected_month
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\edit\OneDrive\Py Scripts\Tkinter GUI\Schedule App\Schedule_GUI.py", line 67, in open_input_window
    self.handle_input_window_selections()
  File "C:\Users\edit\OneDrive\Py Scripts\Tkinter GUI\Schedule App\Schedule_GUI.py", line 58, in __init__
    self.open_input_window()
  File "C:\Users\edit\OneDrive\Py Scripts\Tkinter GUI\Schedule App\Schedule_GUI.py", line 116, in <module>
    app = App()
          ^^^^^
AttributeError: 'InputWindow' object has no attribute 'selected_month'

谢谢您的帮助,我当然还有很多东西要学。

python python-3.x class tkinter ttk
1个回答
0
投票

发布问题时,请提供一个可以独立运行的代码,无论“功能”是什么,它都没有包含在内,需要进行修改才能找到您所在的错误。

你的问题很简单

class InputWindow(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        # Customize the top-level window as needed
        self.title("Schedule Selection")
        self.geometry("400x500")
        self.selected_month = None ##added default value
        self.selected_year = None ##added default value

这 2 个变量在调用

confirm_selections()
之前并不存在。在代码中,您生成
InputWindow
类,然后立即在
handle_input_window_selections()
函数中检查这些值。这发生在调用
confirm_selections()
之前。

如果您希望此操作在类外发生,请将命令添加到类中。

class InputWindow(tk.Toplevel):
    def __init__(self, parent, callback):
        ##...all other current code
        self.sel_button = tk.Button(self, text="Confirm", command=callback)
        ##...all other current code
class App(tk.Tk):
    ##...all other code
    def open_input_window(self):
        self.input_window = InputWindow(self, self.handle_input_window_selections)
    def handle_input_window_selections(self, *args):
        selected_month = self.input_window.select_schedule_month.get()
        selected_year = self.input_window.select_schedule_year.get()
   ##...all other current code
© www.soinside.com 2019 - 2024. All rights reserved.