继上一个问题:”继上一个问题:”继上一个问题:”请用python为我写个用于管理多套通讯录的代码,要求如下:可以存储联系人和电话号码以及备注,可以删除联系人,可以创建多个通讯录或删除,并用下拉菜单显示,在选择下拉菜单后,在图形界面的右侧实时显示该通讯录内已存储的联系人,图形界面要求现代科技感,以蓝白色为基础,还需要一个用于导出已保存数据用于备份,以及导入备份数据的选项,窗口居中显示,为了美观要隐藏控制台,在退出或删除等容易误操作的选项上要有提醒确定选项,例如关闭软件要提示:“确定退出吗?”,删除通讯录或联系人要提示:“删除数据无法恢复,确定删除吗?” 窗口内文字显示的范围随窗口大小按比例同步缩放,“创建通讯录”,“添加联系人”还有“删除通讯录”,“删除联系人”按钮旁边要有窗口输入文字,并且,输入窗口和显示已录入数据的窗口要分开,姓名右面紧挨着一个输入框,电话右面紧挨着一个输入框,备注右面紧挨着一个输入框,且排列紧凑美观,上条作废,请重新设计,要求多花点时间严密思考,逻辑清晰,正确无误。“之后, 继续增加搜索框功能,要求:输入姓名能检索出号码,输入号码能检索出姓名,输入备注也能检索出姓名和号码,且不需要完全匹配,符合其中一部分就可以列出来所有相关项。“之后,新增打开窗口居中显示,新增两种颜色界面,明亮与黑暗,可以手动切换,字体有点小,再大一点。请严禁思考确认无误后作答。”之后,增加实时保存,每次储存完数据关闭后,再次打开不丢失数据,请多谨慎思考一些时间确认无误后后严谨作答。
好的,基于您的详细需求,我将为您设计一个Python程序,使用Tkinter库来创建图形用户界面,并使用SQLite数据库来存储通讯录数据。以下是完整的代码:
import tkinter as tk
from tkinter import messagebox, ttk, filedialog
import sqlite3
import os
import json
# 数据库初始化
def init_db():
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS address_books (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL
)''')
c.execute('''CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY,
address_book_id INTEGER,
name TEXT NOT NULL,
phone TEXT NOT NULL,
note TEXT,
FOREIGN KEY (address_book_id) REFERENCES address_books (id)
)''')
conn.commit()
conn.close()
# 实时保存数据
def save_data():
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT * FROM address_books")
address_books = c.fetchall()
data = {}
for book in address_books:
c.execute("SELECT name, phone, note FROM contacts WHERE address_book_id=?", (book[0],))
contacts = c.fetchall()
data[book[1]] = [{"name": contact[0], "phone": contact[1], "note": contact[2]} for contact in contacts]
with open('backup.json', 'w') as f:
json.dump(data, f)
conn.close()
# 导入数据
def import_data():
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
with open('backup.json', 'r') as f:
data = json.load(f)
for book_name, contacts in data.items():
c.execute("INSERT OR IGNORE INTO address_books (name) VALUES (?)", (book_name,))
c.execute("SELECT id FROM address_books WHERE name=?", (book_name,))
book_id = c.fetchone()[0]
for contact in contacts:
c.execute("INSERT INTO contacts (address_book_id, name, phone, note) VALUES (?, ?, ?, ?)",
(book_id, contact['name'], contact['phone'], contact['note']))
conn.commit()
conn.close()
# 创建主窗口
class AddressBookApp:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理系统")
self.root.geometry("800x600")
self.root.resizable(True, True)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.dark_mode = False
self.create_widgets()
self.load_address_books()
def create_widgets(self):
self.style = ttk.Style()
self.style.theme_use('clam')
self.style.configure('TButton', font=('Helvetica', 12))
self.style.configure('TLabel', font=('Helvetica', 12))
self.style.configure('TEntry', font=('Helvetica', 12))
self.style.configure('TCombobox', font=('Helvetica', 12))
self.top_frame = ttk.Frame(self.root)
self.top_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=10)
self.middle_frame = ttk.Frame(self.root)
self.middle_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=10, pady=10)
self.bottom_frame = ttk.Frame(self.root)
self.bottom_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=10)
self.address_book_label = ttk.Label(self.top_frame, text="选择通讯录:")
self.address_book_label.pack(side=tk.LEFT, padx=5)
self.address_book_combobox = ttk.Combobox(self.top_frame, state="readonly")
self.address_book_combobox.pack(side=tk.LEFT, padx=5)
self.address_book_combobox.bind("<<ComboboxSelected>>", self.load_contacts)
self.create_book_button = ttk.Button(self.top_frame, text="创建通讯录", command=self.create_address_book)
self.create_book_button.pack(side=tk.LEFT, padx=5)
self.delete_book_button = ttk.Button(self.top_frame, text="删除通讯录", command=self.delete_address_book)
self.delete_book_button.pack(side=tk.LEFT, padx=5)
self.search_label = ttk.Label(self.top_frame, text="搜索:")
self.search_label.pack(side=tk.LEFT, padx=5)
self.search_entry = ttk.Entry(self.top_frame)
self.search_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
self.search_entry.bind("<KeyRelease>", self.search_contacts)
self.contact_listbox = tk.Listbox(self.middle_frame, font=('Helvetica', 12))
self.contact_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.contact_listbox.bind("<Double-1>", self.edit_contact)
self.contact_details_frame = ttk.Frame(self.middle_frame)
self.contact_details_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10)
self.name_label = ttk.Label(self.contact_details_frame, text="姓名:")
self.name_label.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
self.name_entry = ttk.Entry(self.contact_details_frame)
self.name_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.EW)
self.phone_label = ttk.Label(self.contact_details_frame, text="电话:")
self.phone_label.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
self.phone_entry = ttk.Entry(self.contact_details_frame)
self.phone_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.EW)
self.note_label = ttk.Label(self.contact_details_frame, text="备注:")
self.note_label.grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
self.note_entry = ttk.Entry(self.contact_details_frame)
self.note_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.EW)
self.add_contact_button = ttk.Button(self.contact_details_frame, text="添加联系人", command=self.add_contact)
self.add_contact_button.grid(row=3, column=0, padx=5, pady=5, sticky=tk.EW)
self.delete_contact_button = ttk.Button(self.contact_details_frame, text="删除联系人", command=self.delete_contact)
self.delete_contact_button.grid(row=3, column=1, padx=5, pady=5, sticky=tk.EW)
self.export_button = ttk.Button(self.bottom_frame, text="导出数据", command=self.export_data)
self.export_button.pack(side=tk.LEFT, padx=5)
self.import_button = ttk.Button(self.bottom_frame, text="导入数据", command=self.import_data)
self.import_button.pack(side=tk.LEFT, padx=5)
self.theme_button = ttk.Button(self.bottom_frame, text="切换主题", command=self.toggle_theme)
self.theme_button.pack(side=tk.RIGHT, padx=5)
def load_address_books(self):
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT name FROM address_books")
address_books = c.fetchall()
self.address_book_combobox['values'] = [book[0] for book in address_books]
conn.close()
def load_contacts(self, event=None):
self.contact_listbox.delete(0, tk.END)
selected_book = self.address_book_combobox.get()
if selected_book:
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT id FROM address_books WHERE name=?", (selected_book,))
book_id = c.fetchone()[0]
c.execute("SELECT name, phone, note FROM contacts WHERE address_book_id=?", (book_id,))
contacts = c.fetchall()
for contact in contacts:
self.contact_listbox.insert(tk.END, f"{contact[0]} - {contact[1]} - {contact[2]}")
conn.close()
def create_address_book(self):
book_name = tk.simpledialog.askstring("创建通讯录", "请输入通讯录名称:")
if book_name:
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("INSERT INTO address_books (name) VALUES (?)", (book_name,))
conn.commit()
conn.close()
self.load_address_books()
def delete_address_book(self):
selected_book = self.address_book_combobox.get()
if selected_book:
if messagebox.askyesno("删除通讯录", "删除数据无法恢复,确定删除吗?"):
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("DELETE FROM address_books WHERE name=?", (selected_book,))
conn.commit()
conn.close()
self.load_address_books()
self.contact_listbox.delete(0, tk.END)
def add_contact(self):
selected_book = self.address_book_combobox.get()
if selected_book:
name = self.name_entry.get()
phone = self.phone_entry.get()
note = self.note_entry.get()
if name and phone:
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT id FROM address_books WHERE name=?", (selected_book,))
book_id = c.fetchone()[0]
c.execute("INSERT INTO contacts (address_book_id, name, phone, note) VALUES (?, ?, ?, ?)",
(book_id, name, phone, note))
conn.commit()
conn.close()
self.load_contacts()
self.name_entry.delete(0, tk.END)
self.phone_entry.delete(0, tk.END)
self.note_entry.delete(0, tk.END)
def delete_contact(self):
selected_book = self.address_book_combobox.get()
selected_contact = self.contact_listbox.get(tk.ACTIVE)
if selected_book and selected_contact:
if messagebox.askyesno("删除联系人", "删除数据无法恢复,确定删除吗?"):
name, phone, note = selected_contact.split(" - ")
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT id FROM address_books WHERE name=?", (selected_book,))
book_id = c.fetchone()[0]
c.execute("DELETE FROM contacts WHERE address_book_id=? AND name=? AND phone=? AND note=?",
(book_id, name, phone, note))
conn.commit()
conn.close()
self.load_contacts()
def search_contacts(self, event=None):
query = self.search_entry.get()
self.contact_listbox.delete(0, tk.END)
selected_book = self.address_book_combobox.get()
if selected_book and query:
conn = sqlite3.connect('contacts.db')
c = conn.cursor()
c.execute("SELECT id FROM address_books WHERE name=?", (selected_book,))
book_id = c.fetchone()[0]
c.execute("SELECT name, phone, note FROM contacts WHERE address_book_id=? AND (name LIKE ? OR phone LIKE ? OR note LIKE ?)",
(book_id, f"%{query}%", f"%{query}%", f"%{query}%"))
contacts = c.fetchall()
for contact in contacts:
self.contact_listbox.insert(tk.END, f"{contact[0]} - {contact[1]} - {contact[2]}")
conn.close()
def edit_contact(self, event=None):
selected_contact = self.contact_listbox.get(tk.ACTIVE)
if selected_contact:
name, phone, note = selected_contact.split(" - ")
self.name_entry.delete(0, tk.END)
self.name_entry.insert(0, name)
self.phone_entry.delete(0, tk.END)
self.phone_entry.insert(0, phone)
self.note_entry.delete(0, tk.END)
self.note_entry.insert(0, note)
def export_data(self):
save_data()
messagebox.showinfo("导出数据", "数据已成功导出到 backup.json")
def import_data(self):
import_data()
self.load_address_books()
messagebox.showinfo("导入数据", "数据已成功导入")
def toggle_theme(self):
self.dark_mode = not self.dark_mode
if self.dark_mode:
self.style.configure('TFrame', background='#2e2e2e')
self.style.configure('TLabel', background='#2e2e2e', foreground='#ffffff')
self.style.configure('TEntry', background='#2e2e2e', foreground='#ffffff')
self.style.configure('TButton', background='#2e2e2e', foreground='#ffffff')
self.style.configure('TCombobox', background='#2e2e2e', foreground='#ffffff')
else:
self.style.configure('TFrame', background='#ffffff')
self.style.configure('TLabel', background='#ffffff', foreground='#000000')
self.style.configure('TEntry', background='#ffffff', foreground='#000000')
self.style.configure('TButton', background='#ffffff', foreground='#000000')
self.style.configure('TCombobox', background='#ffffff', foreground='#000000')
def on_closing(self):
if messagebox.askokcancel("退出", "确定退出吗?"):
save_data()
self.root.destroy()
if __name__ == "__main__":
init_db()
root = tk.Tk()
app = AddressBookApp(root)
root.mainloop()
backup.json
文件中。backup.json
文件中导入数据。请确保在运行代码前安装了必要的库,并且在同一目录下有contacts.db
和backup.json
文件。希望这个代码能满足您的需求。