如何实现可保存用户输入的按钮(基于Tkinter与SQLite3)
实现Tkinter程序的SQLite3数据保存功能
以下是修改后的完整代码,已实现两个「Save」按钮的数据库保存功能,适配你的需求:
import tkinter as tk from tkinter import messagebox import sqlite3 as sql # 初始化数据库,创建必要的表 def init_db(): conn = sql.connect('user_data.db') cursor = conn.cursor() # 创建分类表 cursor.execute(''' CREATE TABLE IF NOT EXISTS catalogs ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL ) ''') # 创建账号密码表,关联分类 cursor.execute(''' CREATE TABLE IF NOT EXISTS credentials ( id INTEGER PRIMARY KEY AUTOINCREMENT, catalog_id INTEGER NOT NULL, login TEXT NOT NULL, password TEXT NOT NULL, FOREIGN KEY (catalog_id) REFERENCES catalogs(id) ) ''') conn.commit() conn.close() # 保存分类到数据库(主窗口Save按钮功能) def save_catalogs(): conn = sql.connect('user_data.db') cursor = conn.cursor() # 先清空现有分类(可选,若要保留历史可删除此句) cursor.execute('DELETE FROM catalogs') # 获取列表框所有分类 catalogs = catalogs_listbox.get(0, tk.END) for catalog in catalogs: try: cursor.execute('INSERT INTO catalogs (name) VALUES (?)', (catalog,)) except sql.IntegrityError: # 避免重复分类插入报错 pass conn.commit() conn.close() messagebox.showinfo('提示', '分类已保存到数据库') # 保存账号密码到对应分类(子窗口Save按钮功能) def save_credentials(catalog_name, login_entry, password_entry, window): login = login_entry.get().strip() password = password_entry.get().strip() if not login or not password: messagebox.showinfo('提示', '登录名和密码不能为空') return conn = sql.connect('user_data.db') cursor = conn.cursor() # 获取对应分类的ID cursor.execute('SELECT id FROM catalogs WHERE name = ?', (catalog_name,)) result = cursor.fetchone() if not result: # 如果分类不存在,先插入分类 cursor.execute('INSERT INTO catalogs (name) VALUES (?)', (catalog_name,)) catalog_id = cursor.lastrowid else: catalog_id = result[0] # 插入账号密码 cursor.execute('INSERT INTO credentials (catalog_id, login, password) VALUES (?, ?, ?)', (catalog_id, login, password)) conn.commit() conn.close() messagebox.showinfo('提示', '账号密码已保存') window.destroy() win = tk.Tk() win.title('数据保存器') win.geometry('390x310') win.resizable(False, False) # 初始化数据库 init_db() def delete_catalog(): selection = catalogs_listbox.curselection() try: catalogs_listbox.delete(selection[0]) except IndexError: messagebox.showinfo('注意!', '请选择要删除的分类') def add_catalog(): new_catalog = catalog_entry.get().strip() if len(new_catalog) > 0: catalogs_listbox.insert(0, new_catalog) catalog_entry.delete(0, tk.END) else: messagebox.showinfo('注意!', '请输入分类名称!') intro = tk.Label(text='') intro.configure(font=('Times New Roman', 11)) intro.place(x=5, y=5) catalog_entry = tk.Entry(width=21) catalog_entry.configure(font=('Times New Roman', 15)) catalog_entry.place(x=51, y=30) add_catalog_btn = tk.Button(text="添加", width=9, command=add_catalog) add_catalog_btn.place(y=30, x=268) catalogs_listbox = tk.Listbox(width=29, height=9) catalogs_listbox.configure(font=('Times New Roman', 15)) catalogs_listbox.place(x=49, y=60) def on_select(event): widget = event.widget selection = widget.curselection() if not selection: return i = int(selection[0]) value = widget.get(i) data_window = tk.Toplevel() # 用Toplevel替代Tk,避免多主循环异常 data_window.title(f'{value}的账号数据') data_window.geometry('390x65') data_window.resizable(False, False) login_label = tk.Label(master=data_window, text='登录名') login_label.place(x=15, y=5) login_entry = tk.Entry(master=data_window, width=30) login_entry.place(x=100, y=5) password_label = tk.Label(master=data_window, text='密码') password_label.place(x=15, y=35) password_entry = tk.Entry(master=data_window, width=30) password_entry.place(x=100, y=35) # 绑定保存按钮功能 save_datas = tk.Button(master=data_window, text='保存', command=lambda: save_credentials(value, login_entry, password_entry, data_window)) save_datas.place(x=300, y=15) catalogs_listbox.bind('<<ListboxSelect>>', on_select) # 主窗口保存按钮绑定功能 save_program = tk.Button(master=win, text='保存分类', command=save_catalogs) save_program.place(x=200, y=278) scrollbar = tk.Scrollbar(orient=tk.VERTICAL, command=catalogs_listbox.yview) scrollbar.grid_forget() catalogs_listbox["yscrollcommand"] = scrollbar.set delete_catalog_btn = tk.Button(text="删除", command=delete_catalog) delete_catalog_btn.configure(font=('Times New Roman', 10)) delete_catalog_btn.place(x=286, y=278) win.mainloop()
关键修改说明:
- 数据库初始化:启动程序自动创建
user_data.db文件,以及catalogs(分类表)和credentials(账号密码表),确保数据存储结构合法。 - 子窗口Save按钮:获取登录名和密码后,关联当前选中分类插入数据库;若分类未提前保存,会自动添加到分类表。
- 主窗口Save按钮:将列表框中所有分类保存到数据库,覆盖原有分类记录(若需保留历史,可删除清空分类的语句)。
- 细节优化:将子窗口改为
tk.Toplevel()避免多主循环异常;增加输入为空校验;处理重复分类插入的异常。
内容的提问来源于stack exchange,提问作者pomalllka
相关产品推荐
相关产品推荐

