基于SQLite3与CustomTkinter的读书记录桌面应用:笔记查看按钮实现方案咨询
解决方案
我来帮你搞定这个需求!要实现同一行显示笔记按钮(无笔记时隐藏),并且点击按钮弹出窗口查看长笔记,我们需要做几个关键改动,下面一步步来:
1. 新增查看笔记的弹窗函数
首先要写一个函数,用来弹出新窗口显示笔记内容。我们把它放在MyFrame类里,和书籍列表逻辑关联更紧密。
2. 修改书籍列表渲染逻辑
在view方法里遍历每本书时,检查prise_de_note字段是否有有效内容:
- 如果有非空笔记,就创建按钮和书名标签放在同一行(不同列)
- 如果没有笔记,就不渲染这个按钮
3. 添加列表自动刷新功能
现在添加新书后列表不会自动更新,所以我们要在添加完成后调用刷新方法,同时先清空旧控件避免重复渲染。
修改后的完整代码
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"An error occured while creating the table : {e}") # 初始化数据库表 crea_biblio() class MyFrame(ctk.CTkScrollableFrame): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) self.view() def open_note_window(self, note_content): """弹出窗口显示笔记内容""" note_window = ctk.CTkToplevel(self) note_window.title("笔记详情") note_window.geometry("400x300") # 用文本框显示长笔记,设置为只读防止误改 note_text = ctk.CTkTextbox(note_window, wrap="word") note_text.pack(padx=15, pady=15, fill="both", expand=True) note_text.insert("1.0", note_content) note_text.configure(state="disabled") 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} écrit par {auteur}") label.grid(row=i, column=1, padx=20, pady=20, sticky="w") # 只有笔记非空时才显示按钮 if note and note.strip(): view_btn = ctk.CTkButton( self, text="查看笔记", command=lambda n=note: self.open_note_window(n), width=80 ) view_btn.grid(row=i, column=2, padx=10, pady=20) except Exception as e: print(f'An error occured while loading books : {e}') class App(ctk.CTk): def __init__(self): super().__init__() self.geometry("700x500") # 加宽窗口给按钮腾空间 self.title("我的书籍库") # 左侧输入区域 self.entry = ctk.CTkEntry(self, placeholder_text="Titre du livre") self.entry.grid(row=0, column=0, padx=20, pady=10) self.entry2 = ctk.CTkEntry(self, placeholder_text="Auteur") self.entry2.grid(row=1, column=0, padx=20, pady=10) self.button = ctk.CTkButton(self, text="Ajouter le livre", command=self.button_click) self.button.grid(row=2, 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=3, padx=20, pady=20, sticky="nsew") # 布局权重设置,让列表框可以自适应窗口拉伸 self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) def button_click(self): titre = self.entry.get().strip() auteur = self.entry2.get().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) VALUES (?, ?);" cursor.execute(sql, (titre, auteur)) conn.commit() print("书籍添加成功!") except Exception as e: print(f"An error occurred while inserting the book: {e}") # 清空输入框并刷新书籍列表 self.entry.delete(0, "end") self.entry2.delete(0, "end") self.my_frame.view() if __name__ == "__main__": app = App() app.mainloop()
关键改动说明
open_note_window方法:创建顶层弹窗,用CTkTextbox适配长文本显示,设置只读模式防止误编辑。- 按钮显示逻辑:通过
note.strip()判断笔记是否为有效内容,避免空字符串或空格导致按钮误显示;用lambda传递当前书籍的笔记内容给弹窗函数。 - 列表刷新:在
view方法开头销毁所有旧控件,添加新书后调用self.my_frame.view()实现自动刷新。 - 布局优化:加宽主窗口、调整
grid的sticky属性和权重,让列表区域可以自适应窗口大小变化。
这样就完全实现了你要的功能:有笔记的书籍条目同一行显示按钮,点击弹出窗口查看长笔记,无笔记时按钮自动隐藏,而且添加新书后列表会实时更新。
内容的提问来源于stack exchange,提问作者Hugo
相关产品推荐
相关产品推荐

