SQLite 資料庫 -4 一對一關聯
一對一關聯
操作步驟:
1. 建立資料庫: 點擊「1. 建立資料庫」,它會創建
MySchoolDB.db檔案和score2資料表。2. 新增資料: 點擊「2. 新增資料」,輸入學號和兩門課程的分數後確定。
5. 顯示所有資料: 點擊「5. 顯示所有資料」,成績資料會顯示在下方的表格中。
3. 更正資料: 在表格中點選一列資料,然後點擊「3. 更正資料」,可以修改分數但不能修改學號。
4. 刪除資料: 在表格中點選一列資料,然後點擊「4. 刪除資料」,確認後該筆成績會被刪除。
6. 刪除資料庫: 點擊「6. 刪除資料庫」會刪除整個
MySchoolDB.db檔案。
import tkinter as tk
from tkinter import messagebox, simpledialog, ttk
import sqlite3
# --- 資料庫操作類別 ---
class DatabaseManager:
def __init__(self, db_name="MySchoolDB.db"):
self.db_name = db_name
self.conn = None
self.cursor = None
def connect(self):
"""建立資料庫連線"""
try:
self.conn = sqlite3.connect(self.db_name)
self.cursor = self.conn.cursor()
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"無法連線到資料庫: {e}")
self.conn = None
self.cursor = None
def close(self):
"""關閉資料庫連線"""
if self.conn:
self.conn.close()
def create_tables(self):
"""1. 建立資料庫(如果不存在)及資料表 student2 和 score2"""
self.connect()
if not self.conn:
return False
try:
# 建立 student2 資料表
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS student2 (
學號 TEXT PRIMARY KEY,
姓名 TEXT NOT NULL,
性別 TEXT
)
''')
# 建立 score2 資料表 (使用學號作為主鍵和外鍵,實現一對一)
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS score2 (
學號 TEXT PRIMARY KEY,
資料庫 INTEGER,
手機程式 INTEGER,
FOREIGN KEY (學號) REFERENCES student2(學號) ON DELETE CASCADE
)
''')
self.conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"建立資料表失敗: {e}")
return False
finally:
self.close()
def insert_data(self, stu_data, score_data):
"""2. 新增資料 (同時新增學生資料和成績資料)"""
self.connect()
if not self.conn:
return False
stu_id, name, gender = stu_data
db_score, mobile_score = score_data
try:
# 檢查學號是否已存在
self.cursor.execute("SELECT 學號 FROM student2 WHERE 學號=?", (stu_id,))
if self.cursor.fetchone():
messagebox.showwarning("新增失敗", f"學號 {stu_id} 已存在!")
return False
# 插入 student2
self.cursor.execute("INSERT INTO student2 (學號, 姓名, 性別) VALUES (?, ?, ?)", (stu_id, name, gender))
# 插入 score2
self.cursor.execute("INSERT INTO score2 (學號, 資料庫, 手機程式) VALUES (?, ?, ?)", (stu_id, db_score, mobile_score))
self.conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"新增資料失敗: {e}")
self.conn.rollback()
return False
finally:
self.close()
def update_data(self, stu_id, stu_data=None, score_data=None):
"""3. 更正資料 (更新學生資料或成績資料)"""
self.connect()
if not self.conn:
return False
try:
# 檢查學號是否存在
self.cursor.execute("SELECT 學號 FROM student2 WHERE 學號=?", (stu_id,))
if not self.cursor.fetchone():
messagebox.showwarning("更正失敗", f"學號 {stu_id} 不存在!")
return False
if stu_data:
name, gender = stu_data
self.cursor.execute("UPDATE student2 SET 姓名=?, 性別=? WHERE 學號=?", (name, gender, stu_id))
if score_data:
db_score, mobile_score = score_data
# 嘗試更新 score2,如果不存在則插入 (因為是一對一,所以學生表有資料,成績表也應該有,但為保險起見使用 REPLACE)
# 但一般情況下,一對一的資料應該同時建立,這裡使用 UPDATE
self.cursor.execute("UPDATE score2 SET 資料庫=?, 手機程式=? WHERE 學號=?", (db_score, mobile_score, stu_id))
self.conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"更正資料失敗: {e}")
self.conn.rollback()
return False
finally:
self.close()
def delete_data(self, stu_id):
"""4. 刪除資料 (刪除學生資料和相關成績資料)"""
self.connect()
if not self.conn:
return False
try:
# 檢查學號是否存在
self.cursor.execute("SELECT 學號 FROM student2 WHERE 學號=?", (stu_id,))
if not self.cursor.fetchone():
messagebox.showwarning("刪除失敗", f"學號 {stu_id} 不存在!")
return False
# 刪除 student2 的資料。由於 score2 設有 ON DELETE CASCADE,相關的成績也會被刪除。
self.cursor.execute("DELETE FROM student2 WHERE 學號=?", (stu_id,))
self.conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"刪除資料失敗: {e}")
self.conn.rollback()
return False
finally:
self.close()
def get_all_data(self):
"""5. 顯示所有資料 (連線 student2 和 score2)"""
self.connect()
if not self.conn:
return []
try:
# 使用 LEFT JOIN 來連線兩個表,即使 score2 沒有資料也能顯示 student2 的基本資訊
self.cursor.execute('''
SELECT
s.學號, s.姓名, s.性別, c.資料庫, c.手機程式
FROM
student2 s
LEFT JOIN
score2 c ON s.學號 = c.學號
ORDER BY s.學號
''')
rows = self.cursor.fetchall()
return rows
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"查詢資料失敗: {e}")
return []
finally:
self.close()
def delete_database_file(self):
"""6. 刪除資料庫檔案"""
import os
if os.path.exists(self.db_name):
try:
# 確保連線已關閉
self.close()
os.remove(self.db_name)
return True
except OSError as e:
messagebox.showerror("刪除失敗", f"無法刪除資料庫檔案 {self.db_name}: {e}")
return False
else:
messagebox.showwarning("刪除失敗", f"資料庫檔案 {self.db_name} 不存在。")
return False
# --- Tkinter GUI 應用程式類別 ---
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("學生資料與成績管理系統")
self.db = DatabaseManager("MySchoolDB.db")
# 設定視窗大小和位置
self.geometry("800x600")
self.create_widgets()
self.load_data_to_treeview()
def create_widgets(self):
# 功能按鈕區塊
button_frame = tk.Frame(self, padx=10, pady=10)
button_frame.pack(fill='x')
# 按鈕清單: (文字, 執行函數)
buttons = [
("1. 建立資料庫", self.create_db_command),
("2. 新增資料", self.add_data_dialog),
("3. 更正資料", self.update_data_dialog),
("4. 刪除資料", self.delete_data_dialog),
("5. 顯示所有資料", self.load_data_to_treeview),
("6. 刪除資料庫", self.delete_db_command)
]
for i, (text, command) in enumerate(buttons):
btn = tk.Button(button_frame, text=text, command=command, width=15)
btn.grid(row=0, column=i, padx=5, pady=5)
# 顯示資料的 Treeview
self.tree = ttk.Treeview(self, columns=('學號', '姓名', '性別', '資料庫', '手機程式'), show='headings')
# 設定欄位標題和寬度
self.tree.heading('學號', text='學號')
self.tree.column('學號', width=80, anchor='center')
self.tree.heading('姓名', text='姓名')
self.tree.column('姓名', width=100, anchor='center')
self.tree.heading('性別', text='性別')
self.tree.column('性別', width=50, anchor='center')
self.tree.heading('資料庫', text='資料庫(分數)')
self.tree.column('資料庫', width=100, anchor='center')
self.tree.heading('手機程式', text='手機程式(分數)')
self.tree.column('手機程式', width=120, anchor='center')
# 新增捲軸
vsb = ttk.Scrollbar(self, orient="vertical", command=self.tree.yview)
vsb.pack(side='right', fill='y')
self.tree.configure(yscrollcommand=vsb.set)
self.tree.pack(fill='both', expand=True, padx=10, pady=10)
# --- 功能執行函數 ---
def create_db_command(self):
"""執行建立資料庫和資料表的命令"""
if self.db.create_tables():
messagebox.showinfo("成功", "資料庫 MySchoolDB.db 及其資料表 (student2, score2) 已成功建立或已存在。")
self.load_data_to_treeview() # 重新整理顯示
else:
# 錯誤已在 DatabaseManager 中處理
pass
def load_data_to_treeview(self):
"""5. 顯示所有資料到 Treeview"""
# 清空現有資料
for item in self.tree.get_children():
self.tree.delete(item)
data = self.db.get_all_data()
if data:
for row in data:
# 處理分數為 None 的情況 (在 LEFT JOIN 中,如果 score2 沒資料,分數會是 None)
display_row = list(row)
display_row[3] = display_row[3] if display_row[3] is not None else 'N/A'
display_row[4] = display_row[4] if display_row[4] is not None else 'N/A'
self.tree.insert('', tk.END, values=display_row)
messagebox.showinfo("查詢成功", f"成功載入 {len(data)} 筆資料。")
else:
messagebox.showinfo("查詢結果", "資料庫中沒有資料,或連線失敗。")
def add_data_dialog(self):
"""2. 新增資料的對話框"""
dialog = DataDialog(self, "新增資料", mode='add')
if dialog.result and self.db.insert_data(dialog.result['stu'], dialog.result['score']):
messagebox.showinfo("成功", "資料新增成功!")
self.load_data_to_treeview() # 重新整理顯示
def update_data_dialog(self):
"""3. 更正資料的對話框"""
# 取得選定的項目
selected_item = self.tree.focus()
if not selected_item:
messagebox.showwarning("更正失敗", "請先在列表中選取一筆要更正的資料。")
return
# 取得學號
stu_id = self.tree.item(selected_item, 'values')[0]
dialog = DataDialog(self, "更正資料", mode='update', initial_data=self.tree.item(selected_item, 'values'))
if dialog.result:
stu_data = (dialog.result['stu'][1], dialog.result['stu'][2]) # 姓名, 性別
score_data = (dialog.result['score'][0], dialog.result['score'][1]) # 資料庫, 手機程式
if self.db.update_data(stu_id, stu_data, score_data):
messagebox.showinfo("成功", f"學號 {stu_id} 資料更正成功!")
self.load_data_to_treeview() # 重新整理顯示
def delete_data_dialog(self):
"""4. 刪除資料的對話框"""
selected_item = self.tree.focus()
if not selected_item:
messagebox.showwarning("刪除失敗", "請先在列表中選取一筆要刪除的資料。")
return
stu_id = self.tree.item(selected_item, 'values')[0]
name = self.tree.item(selected_item, 'values')[1]
if messagebox.askyesno("確認刪除", f"確定要刪除學號 {stu_id} (姓名: {name}) 的所有資料嗎?"):
if self.db.delete_data(stu_id):
messagebox.showinfo("成功", "資料刪除成功!")
self.load_data_to_treeview() # 重新整理顯示
# 錯誤已在 DatabaseManager 中處理
def delete_db_command(self):
"""6. 刪除資料庫檔案"""
if messagebox.askyesno("確認刪除資料庫", f"**警告:** 確定要刪除整個資料庫檔案 {self.db.db_name} 嗎?所有資料將會遺失!"):
if self.db.delete_database_file():
messagebox.showinfo("成功", "資料庫檔案已刪除。")
self.load_data_to_treeview() # 重新整理顯示為空
# --- 輸入/更正資料的獨立對話框 ---
class DataDialog(simpledialog.Dialog):
def __init__(self, parent, title=None, mode='add', initial_data=None):
self.mode = mode
self.initial_data = initial_data
super().__init__(parent, title)
def body(self, master):
tk.Label(master, text="學號:").grid(row=0, sticky='w')
tk.Label(master, text="姓名:").grid(row=1, sticky='w')
tk.Label(master, text="性別 (男/女):").grid(row=2, sticky='w')
tk.Label(master, text="資料庫分數:").grid(row=3, sticky='w')
tk.Label(master, text="手機程式分數:").grid(row=4, sticky='w')
self.e1 = tk.Entry(master)
self.e2 = tk.Entry(master)
self.e3 = tk.Entry(master)
self.e4 = tk.Entry(master)
self.e5 = tk.Entry(master)
self.e1.grid(row=0, column=1, padx=5, pady=5)
self.e2.grid(row=1, column=1, padx=5, pady=5)
self.e3.grid(row=2, column=1, padx=5, pady=5)
self.e4.grid(row=3, column=1, padx=5, pady=5)
self.e5.grid(row=4, column=1, padx=5, pady=5)
if self.mode == 'update' and self.initial_data:
# 載入現有資料
self.e1.insert(0, self.initial_data[0]) # 學號
self.e2.insert(0, self.initial_data[1]) # 姓名
self.e3.insert(0, self.initial_data[2]) # 性別
self.e4.insert(0, self.initial_data[3] if self.initial_data[3] != 'N/A' else '') # 資料庫
self.e5.insert(0, self.initial_data[4] if self.initial_data[4] != 'N/A' else '') # 手機程式
self.e1.config(state='readonly') # 更正模式下,學號不可修改
if self.mode == 'add':
tk.Label(master, text="*新增模式下,學號必須為新的*").grid(row=5, column=0, columnspan=2, sticky='w')
if self.mode == 'update':
tk.Label(master, text="*更正模式下,學號不可修改*").grid(row=5, column=0, columnspan=2, sticky='w')
return self.e1 # 初始焦點
def validate(self):
"""資料驗證"""
stu_id = self.e1.get().strip()
name = self.e2.get().strip()
gender = self.e3.get().strip()
db_score_str = self.e4.get().strip()
mobile_score_str = self.e5.get().strip()
if not stu_id or not name or not gender:
messagebox.showwarning("輸入錯誤", "學號、姓名和性別為必填欄位。")
return 0
if gender not in ('男', '女'):
messagebox.showwarning("輸入錯誤", "性別請輸入 '男' 或 '女'。")
return 0
# 分數驗證
try:
db_score = int(db_score_str)
if not (0 <= db_score <= 100):
messagebox.showwarning("輸入錯誤", "資料庫分數必須在 0-100 之間。")
return 0
except ValueError:
messagebox.showwarning("輸入錯誤", "資料庫分數必須為整數。")
return 0
try:
mobile_score = int(mobile_score_str)
if not (0 <= mobile_score <= 100):
messagebox.showwarning("輸入錯誤", "手機程式分數必須在 0-100 之間。")
return 0
except ValueError:
messagebox.showwarning("輸入錯誤", "手機程式分數必須為整數。")
return 0
return 1
def apply(self):
"""將驗證後的資料存儲到 result"""
stu_id = self.e1.get().strip()
name = self.e2.get().strip()
gender = self.e3.get().strip()
db_score = int(self.e4.get().strip())
mobile_score = int(self.e5.get().strip())
self.result = {
'stu': (stu_id, name, gender),
'score': (db_score, mobile_score)
}
if __name__ == '__main__':
app = Application()
app.mainloop()
學生資料1
import tkinter as tk
from tkinter import messagebox, simpledialog, ttk
import sqlite3
import os
# --- 資料庫操作類別 ---
class DatabaseManager:
"""管理 MySchoolDB.db 中 student2 資料表的 CRUD 操作。"""
def __init__(self, db_name="MySchoolDB.db"):
self.db_name = db_name
self.table_name = "student2"
def connect(self):
"""建立資料庫連線"""
try:
conn = sqlite3.connect(self.db_name)
return conn
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"無法連線到資料庫: {e}")
return None
def create_table(self):
"""1. 建立資料表 (MySchoolDB.db 及 student2 表)"""
conn = self.connect()
if not conn:
return False
try:
cursor = conn.cursor()
# 建立 student2 資料表
# 欄位: 學號 (主鍵), 姓名, 性別
cursor.execute(f'''
CREATE TABLE IF NOT EXISTS {self.table_name} (
學號 TEXT PRIMARY KEY,
姓名 TEXT NOT NULL,
性別 TEXT
)
''')
conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"建立資料表失敗: {e}")
return False
finally:
conn.close()
def insert_data(self, stu_id, name, gender):
"""2. 新增資料"""
conn = self.connect()
if not conn:
return False
try:
cursor = conn.cursor()
# 檢查學號是否已存在
cursor.execute(f"SELECT 學號 FROM {self.table_name} WHERE 學號=?", (stu_id,))
if cursor.fetchone():
messagebox.showwarning("新增失敗", f"學號 {stu_id} 已存在!")
return False
cursor.execute(f"INSERT INTO {self.table_name} (學號, 姓名, 性別) VALUES (?, ?, ?)",
(stu_id, name, gender))
conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"新增資料失敗: {e}")
conn.rollback()
return False
finally:
conn.close()
def update_data(self, stu_id, name, gender):
"""3. 更正資料"""
conn = self.connect()
if not conn:
return False
try:
cursor = conn.cursor()
# 檢查學號是否存在
cursor.execute(f"SELECT 學號 FROM {self.table_name} WHERE 學號=?", (stu_id,))
if not cursor.fetchone():
messagebox.showwarning("更正失敗", f"學號 {stu_id} 不存在!")
return False
cursor.execute(f"UPDATE {self.table_name} SET 姓名=?, 性別=? WHERE 學號=?",
(name, gender, stu_id))
conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"更正資料失敗: {e}")
conn.rollback()
return False
finally:
conn.close()
def delete_data(self, stu_id):
"""4. 刪除資料"""
conn = self.connect()
if not conn:
return False
try:
cursor = conn.cursor()
# 檢查學號是否存在
cursor.execute(f"SELECT 學號 FROM {self.table_name} WHERE 學號=?", (stu_id,))
if not cursor.fetchone():
messagebox.showwarning("刪除失敗", f"學號 {stu_id} 不存在!")
return False
cursor.execute(f"DELETE FROM {self.table_name} WHERE 學號=?", (stu_id,))
conn.commit()
return True
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"刪除資料失敗: {e}")
conn.rollback()
return False
finally:
conn.close()
def get_all_data(self):
"""5. 顯示所有資料"""
conn = self.connect()
if not conn:
return []
try:
cursor = conn.cursor()
cursor.execute(f"SELECT 學號, 姓名, 性別 FROM {self.table_name} ORDER BY 學號")
rows = cursor.fetchall()
return rows
except sqlite3.Error as e:
messagebox.showerror("資料庫錯誤", f"查詢資料失敗: {e}")
return []
finally:
conn.close()
def delete_database_file(self):
"""6. 刪除資料庫檔案"""
if os.path.exists(self.db_name):
try:
# 確保所有連線都已關閉
# (因為 connect/close 都是在各方法內操作,所以通常不會有問題)
os.remove(self.db_name)
return True
except OSError as e:
messagebox.showerror("刪除失敗", f"無法刪除資料庫檔案 {self.db_name}: {e}\n請確認是否有其他程式正在使用此檔案。")
return False
else:
messagebox.showwarning("刪除失敗", f"資料庫檔案 {self.db_name} 不存在。")
return False
# --- Tkinter GUI 應用程式類別 ---
class Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("學生資料管理系統 (student2)")
self.db = DatabaseManager()
self.geometry("600x450")
self.create_widgets()
self.load_data_to_treeview() # 啟動時載入資料
def create_widgets(self):
# 功能按鈕區塊
button_frame = tk.Frame(self, padx=10, pady=10)
button_frame.pack(fill='x')
# 按鈕清單
buttons = [
("1. 建立資料庫", self.create_db_command),
("2. 新增資料", self.add_data_dialog),
("3. 更正資料", self.update_data_dialog),
("4. 刪除資料", self.delete_data_command),
("5. 顯示所有資料", self.load_data_to_treeview),
("6. 刪除資料庫", self.delete_db_command)
]
# 將按鈕排成一行
for i, (text, command) in enumerate(buttons):
btn = tk.Button(button_frame, text=text, command=command, width=12)
btn.grid(row=0, column=i, padx=5, pady=5)
# 顯示資料的 Treeview
self.tree = ttk.Treeview(self, columns=('學號', '姓名', '性別'), show='headings')
# 設定欄位標題和寬度
self.tree.heading('學號', text='學號')
self.tree.column('學號', width=120, anchor='center')
self.tree.heading('姓名', text='姓名')
self.tree.column('姓名', width=150, anchor='w')
self.tree.heading('性別', text='性別')
self.tree.column('性別', width=80, anchor='center')
self.tree.pack(fill='both', expand=True, padx=10, pady=10)
# --- 功能執行函數 ---
def create_db_command(self):
"""執行建立資料庫和資料表的命令"""
if self.db.create_table():
messagebox.showinfo("成功", "資料庫 MySchoolDB.db 及其資料表 student2 已成功建立或已存在。")
self.load_data_to_treeview()
# 錯誤處理已在 DatabaseManager 中完成
def load_data_to_treeview(self):
"""5. 顯示所有資料到 Treeview"""
# 清空現有資料
for item in self.tree.get_children():
self.tree.delete(item)
data = self.db.get_all_data()
if data:
for row in data:
self.tree.insert('', tk.END, values=row)
# messagebox.showinfo("查詢成功", f"成功載入 {len(data)} 筆資料。") # 避免過多彈窗
else:
# messagebox.showinfo("查詢結果", "資料庫中沒有資料,或連線失敗。")
pass
def add_data_dialog(self):
"""2. 新增資料的對話框"""
dialog = StudentDataDialog(self, "新增學生資料", mode='add')
if dialog.result:
stu_id, name, gender = dialog.result
if self.db.insert_data(stu_id, name, gender):
messagebox.showinfo("成功", "資料新增成功!")
self.load_data_to_treeview()
def update_data_dialog(self):
"""3. 更正資料的對話框"""
selected_item = self.tree.focus()
if not selected_item:
messagebox.showwarning("更正失敗", "請先在列表中選取一筆要更正的資料。")
return
initial_data = self.tree.item(selected_item, 'values') # (學號, 姓名, 性別)
stu_id = initial_data[0]
dialog = StudentDataDialog(self, "更正學生資料", mode='update', initial_data=initial_data)
if dialog.result:
# 更正模式下學號不可變,只更新姓名和性別
_, new_name, new_gender = dialog.result
if self.db.update_data(stu_id, new_name, new_gender):
messagebox.showinfo("成功", f"學號 {stu_id} 資料更正成功!")
self.load_data_to_treeview()
def delete_data_command(self):
"""4. 刪除資料"""
selected_item = self.tree.focus()
if not selected_item:
messagebox.showwarning("刪除失敗", "請先在列表中選取一筆要刪除的資料。")
return
stu_id, name, _ = self.tree.item(selected_item, 'values')
if messagebox.askyesno("確認刪除", f"確定要刪除學號 {stu_id} (姓名: {name}) 的資料嗎?"):
if self.db.delete_data(stu_id):
messagebox.showinfo("成功", "資料刪除成功!")
self.load_data_to_treeview()
def delete_db_command(self):
"""6. 刪除資料庫檔案"""
if messagebox.askyesno("確認刪除資料庫", f"**警告:** 確定要刪除整個資料庫檔案 {self.db.db_name} 嗎?所有資料將會遺失!"):
if self.db.delete_database_file():
messagebox.showinfo("成功", "資料庫檔案已刪除。")
self.load_data_to_treeview() # 清空顯示
# --- 輸入/更正資料的獨立對話框 ---
class StudentDataDialog(simpledialog.Dialog):
def __init__(self, parent, title=None, mode='add', initial_data=None):
self.mode = mode
self.initial_data = initial_data
self.result = None
super().__init__(parent, title)
def body(self, master):
tk.Label(master, text="學號:").grid(row=0, sticky='w', padx=5, pady=5)
tk.Label(master, text="姓名:").grid(row=1, sticky='w', padx=5, pady=5)
tk.Label(master, text="性別 (男/女):").grid(row=2, sticky='w', padx=5, pady=5)
self.e1 = tk.Entry(master, width=30)
self.e2 = tk.Entry(master, width=30)
self.e3 = tk.Entry(master, width=30)
self.e1.grid(row=0, column=1, padx=5, pady=5)
self.e2.grid(row=1, column=1, padx=5, pady=5)
self.e3.grid(row=2, column=1, padx=5, pady=5)
if self.mode == 'update' and self.initial_data:
# 載入現有資料
self.e1.insert(0, self.initial_data[0]) # 學號
self.e2.insert(0, self.initial_data[1]) # 姓名
self.e3.insert(0, self.initial_data[2]) # 性別
self.e1.config(state='readonly') # 更正模式下,學號不可修改
return self.e2 # 初始焦點設為姓名
return self.e1 # 初始焦點設為學號
def validate(self):
"""資料驗證"""
stu_id = self.e1.get().strip()
name = self.e2.get().strip()
gender = self.e3.get().strip()
if not stu_id or not name or not gender:
messagebox.showwarning("輸入錯誤", "所有欄位皆為必填。")
return 0
if gender not in ('男', '女'):
messagebox.showwarning("輸入錯誤", "性別請輸入 '男' 或 '女'。")
return 0
return 1
def apply(self):
"""將驗證後的資料存儲到 result"""
stu_id = self.e1.get().strip()
name = self.e2.get().strip()
gender = self.e3.get().strip()
self.result = (stu_id, name, gender)
if __name__ == '__main__':
app = Application()
app.mainloop()
學生成績2





沒有留言:
張貼留言