SQLite数据提交与Frame切换同按钮实现及AttributeError问题求助
Hey there! Let's walk through solving your problem step by step—getting that single button to both submit data to SQLite and switch frames, while fixing that annoying AttributeError along the way.
First, Why the AttributeError?
That error '_tkinter.tkapp' object has no attribute 'confirm_button' means you were trying to access a button named confirm_button from your main Tkinter app object, but the button is actually defined inside your PageOne class. The main app doesn't know about it because it's a property of the PageOne frame instance, not the app itself.
Here's a Working Example
Let's build a complete, minimal version of your project that handles both tasks correctly. I'll break down the key parts so you understand what's going on:
import tkinter as tk from tkinter import messagebox import sqlite3 class MainApp(tk.Tk): def __init__(self): super().__init__() self.title("Project Submission & Frame Switch") # Initialize SQLite database self.setup_database() # Container to hold all frames self.container = tk.Frame(self) self.container.pack(fill="both", expand=True) # Register frames and store references self.frames = {} for FrameClass in (PageOne, PageTwo): frame = FrameClass(parent=self.container, controller=self) self.frames[FrameClass.__name__] = frame frame.grid(row=0, column=0, sticky="nsew") # Start on PageOne self.show_frame("PageOne") def setup_database(self): # Create table if it doesn't exist conn = sqlite3.connect("project_data.db") cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS user_inputs ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL ) ''') conn.commit() conn.close() def submit_to_db(self, content): # Reusable method to save data to SQLite conn = sqlite3.connect("project_data.db") cursor = conn.cursor() cursor.execute("INSERT INTO user_inputs (content) VALUES (?)", (content,)) conn.commit() conn.close() def show_frame(self, frame_name): # Switch between frames using tkraise() frame = self.frames[frame_name] frame.tkraise() class PageOne(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller # Keep reference to main app # Input field self.input_entry = tk.Entry(self, width=40) self.input_entry.pack(pady=20, padx=20) # The dual-function button self.confirm_button = tk.Button( self, text="Submit & Switch Page", command=self.handle_confirm # Bind to our custom method ) self.confirm_button.pack(pady=10) def handle_confirm(self): # Step 1: Get input content user_input = self.input_entry.get().strip() # Validate input isn't empty if not user_input: messagebox.showwarning("Oops!", "Please enter some content first!") return # Step 2: Submit to SQLite using main app's method self.controller.submit_to_db(user_input) # Step 3: Switch to the next frame self.controller.show_frame("PageTwo") class PageTwo(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller tk.Label(self, text="Success! You've switched pages and saved data.").pack(pady=20) tk.Button( self, text="Go Back", command=lambda: self.controller.show_frame("PageOne") ).pack(pady=10) if __name__ == "__main__": app = MainApp() app.mainloop()
Key Fixes & Explanations
- Button Scope: The
confirm_buttonis defined insidePageOne, so we access it viaself.confirm_buttonwithin the class (no need to call it from the main app). - Dual-Function Callback: The
handle_confirmmethod inPageOnedoes three things: validates input, calls the main app'ssubmit_to_dbto save to SQLite, then triggers frame switching viashow_frame. - Controller Pattern: Each frame holds a reference to the main app (
controller), which lets us reuse database logic and frame-switching code across pages. - Database Encapsulation: All SQLite operations are handled in the main app, keeping frame code clean and focused on UI tasks.
Quick Troubleshooting Tips
- If you still get the AttributeError, check where you're referencing
confirm_button—make sure you're not trying to access it from the main app object (selfinMainApp) instead of thePageOneinstance. - Use
print(self)in the line where the error occurs to see what object you're working with—this will confirm if you're accidentally using the main app instead of the frame.
内容的提问来源于stack exchange,提问作者Alex Penhallurick

