如何为带笔记的书籍条目添加查看按钮(CustomTkinter+SQLite3)
解决方案
问题说明
我想要创建一个小型桌面应用,用于查看已阅读的书籍以及我为这些书籍撰写的笔记。我正在使用SQLite3数据库,其中包含ID、书名、作者和笔记字段。但由于笔记内容较长,最好通过点击按钮弹出小窗口来查看笔记。请问如何将该按钮放置在书籍条目旁边,且在没有笔记时不显示?是否需要创建新函数?
修改后的完整代码
import os import sqlite3 import customtkinter as ctk dossier_actuel = os.path.dirname(os.path.abspath(__file__)) chemin_base_donnees = os.path.join(dossier_actuel, "bibliotheque.db") def connection(): return sqlite3.connect(chemin_base_donnees) def crea_biblio(): try: with connection() as conn: cursor = conn.cursor() sql = '''CREATE TABLE IF NOT EXISTS Livres ( id_livre INTEGER PRIMARY KEY AUTOINCREMENT, titre_livre TEXT, auteur_livre TEXT, prise_de_note TEXT );''' cursor.execute(sql) conn.commit() except Exception as e: print(f"创建表时出错: {e}") # 弹出窗口显示笔记的函数 def show_notes(note_content): note_window = ctk.CTkToplevel() note_window.title("查看笔记") note_window.geometry("400x300") # 使用文本框显示长笔记 note_text = ctk.CTkTextbox(note_window, wrap="word") note_text.pack(fill="both", expand=True, padx=10, pady=10) note_text.insert("1.0", note_content) note_text.configure(state="disabled") # 设置为只读 class MyFrame(ctk.CTkScrollableFrame): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) def view(self): # 先清空现有控件,避免重复显示 for widget in self.winfo_children(): widget.destroy() try: with connection() as conn: cursor = conn.cursor() cursor.execute("SELECT titre_livre, auteur_livre, prise_de_note FROM Livres ORDER BY id_livre") lignes = cursor.fetchall() for i, ligne in enumerate(lignes): titre, auteur, note = ligne # 创建书籍信息标签 label = ctk.CTkLabel(self, text=f"{titre} 作者:{auteur}") label.grid(row=i, column=0, padx=20, pady=20, sticky="w") # 判断是否有笔记,有则显示按钮 if note and note.strip(): view_btn = ctk.CTkButton(self, text="查看笔记", command=lambda n=note: show_notes(n)) view_btn.grid(row=i, column=1, padx=10, pady=20) except Exception as e: print(f"加载书籍列表时出错: {e}") class App(ctk.CTk): def __init__(self): super().__init__() self.geometry("700x500") self.title("我的藏书笔记") # 初始化数据库表 crea_biblio() # 添加控件 self.entry = ctk.CTkEntry(self, placeholder_text="书名") self.entry.grid(row=0, column=0, padx=20, pady=10) self.entry2 = ctk.CTkEntry(self, placeholder_text="作者") self.entry2.grid(row=1, column=0, padx=20, pady=10) # 添加笔记输入框(方便测试添加笔记) self.note_entry = ctk.CTkTextbox(self, height=80, placeholder_text="输入笔记内容") self.note_entry.grid(row=2, column=0, padx=20, pady=10, sticky="we") self.button = ctk.CTkButton(self, text="添加书籍", command=self.button_click) self.button.grid(row=3, column=0, padx=20, pady=10) self.my_frame = MyFrame(master=self, width=400, height=400) self.my_frame.grid(row=0, column=1, rowspan=4, padx=20, pady=20, sticky="nsew") # 初始加载书籍列表 self.my_frame.view() def button_click(self): titre = self.entry.get().strip() auteur = self.entry2.get().strip() note = self.note_entry.get("1.0", "end").strip() if not titre or not auteur: print("书名和作者不能为空") return try: with connection() as conn: cursor = conn.cursor() sql = "INSERT INTO Livres (titre_livre, auteur_livre, prise_de_note) VALUES (?, ?, ?);" cursor.execute(sql, (titre, auteur, note)) conn.commit() print("书籍添加成功") except Exception as e: print(f"添加书籍时出错: {e}") # 清空输入框 self.entry.delete(0, "end") self.entry2.delete(0, "end") self.note_entry.delete("1.0", "end") # 刷新书籍列表 self.my_frame.view() app = App() app.mainloop()
关键修改点说明
- 新增
show_notes函数:专门用于弹出新窗口显示笔记内容,用CTkToplevel创建弹窗,CTkTextbox展示长文本并设置为只读,适配长笔记的查看需求。 - 动态显示按钮:在
view方法中遍历书籍数据时,判断prise_de_note是否为非空有效内容,只有存在笔记时才创建并显示"查看笔记"按钮,通过lambda传递当前书籍的笔记内容给弹窗函数。 - 列表刷新机制:添加书籍后调用
self.my_frame.view()刷新列表,同时在view方法开头清空现有控件,避免重复渲染旧数据。 - 完善数据库初始化:在
App的初始化方法中调用crea_biblio(),确保数据库表被正确创建。 - 新增笔记输入框:方便测试添加带笔记的书籍,实际使用中可根据需求调整输入方式(比如单独的编辑窗口)。
内容的提问来源于stack exchange,提问作者Hugo
相关产品推荐
相关产品推荐

