Tkinter应用 - 我的Toplevel窗口不出现,应用卡在主循环中

0 投票
1 回答
47 浏览
提问于 2025-04-11 22:30

我正在尝试制作一个工作日程跟踪器,现在先从标题部分开始。附上的图片展示了完成后设计的样子。

日程标题设计

到目前为止,我有三个类:

  • 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第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'

谢谢你的帮助,我确实还有很多东西需要学习。

1 个回答

暂无回答

撰写回答