You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为带笔记的书籍条目添加查看按钮(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 18:03:11