2023年12月

请输入图片描述

前面的版本有bug,登录界面和主窗口还是会同时显示,更新一下
'''
ver14.py: 登录窗口和主窗口分别显示,前面ver12 ver13 没有解决这个问题
'''

import json
import tkinter as tk
from tkinter import messagebox, simpledialog

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_checked_out = False

    def display_info(self):
        status = "已借出" if self.is_checked_out else "可借阅"
        return f"《{self.title}》 - 作者: {self.author} - 状态: {status}"

    def check_out(self):
        self.is_checked_out = True

    def check_in(self):
        self.is_checked_out = False

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            return f"借阅成功:《{book.title}》"
        else:
            return "抱歉,这本书已经被借出了。"

    def return_book(self, book):
        if book in self.borrowed_books:
            book.check_in()
            self.borrowed_books.remove(book)
            return f"归还成功:《{book.title}》"
        else:
            return "这本书没有被这位用户借阅。"

class LoginApp:
    def __init__(self, root, library_app):
        self.root = root
        self.root.title("用户登录")
        self.library_app = library_app

        self.library_app.root.withdraw()  ## key fix: 确保主窗口在登录之前不会显示

        # 创建 GUI 元素
        self.label = tk.Label(root, text="用户登录", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.username_label = tk.Label(root, text="用户名:")
        self.username_label.pack()
        self.username_entry = tk.Entry(root)
        self.username_entry.pack(pady=5)

        self.password_label = tk.Label(root, text="密码:")
        self.password_label.pack()
        self.password_entry = tk.Entry(root, show="*")
        self.password_entry.pack(pady=10)

        self.login_button = tk.Button(root, text="登录", command=self.login)
        self.login_button.pack(pady=5)

        self.register_button = tk.Button(root, text="注册", command=self.register)
        self.register_button.pack(pady=5)

        root.protocol("WM_DELETE_WINDOW", self.on_closing)
    def on_closing(self):
        # 保存数据并关闭窗口
        print(f"close login window...")
        self.root.destroy()
        self.library_app.root.destroy()

    def login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        user = self.library_app.library.find_user(username, password)
        if user:
            # 关闭登录窗口
            #self.root.destroy()
            self.root.withdraw()
            # 显示主窗口
            self.library_app.root.deiconify()
            self.library_app.show_main_interface(user)
        else:
            messagebox.showwarning("登录失败", "用户名或密码错误。")

    def register(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        if not self.library_app.library.is_username_taken(username):
            new_user = User(username, password)
            self.library_app.library.users.append(new_user)
            messagebox.showinfo("注册成功", "注册成功,请使用新账户登录。")
        else:
            messagebox.showwarning("注册失败", "用户名已被使用,请选择其他用户名。")

class LibraryApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆管理系统")

        self.library = Library()

        # 初始化用户登录界面
        self.login_root = tk.Toplevel(root)
        self.login_app = LoginApp(self.login_root, self)
        # 关闭窗口时触发保存数据操作
        root.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.is_init = False

    def show_main_interface(self, user):
        #self.main_interface = tk.Toplevel(self.root)
        #self.main_interface.title("主界面")
        # 创建 GUI 元素
        if self.is_init:
            return
        self.is_init = True
        self.label = tk.Label(self.root, text=f"欢迎,{user.username}!", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.listbox = tk.Listbox(self.root, selectmode=tk.SINGLE, font=("Helvetica", 12), height=10, width=50)
        self.listbox.pack(pady=10)

        self.borrow_button = tk.Button(self.root, text="借阅图书", command=self.borrow_book)
        self.borrow_button.pack(pady=5)

        self.return_button = tk.Button(self.root, text="归还图书", command=self.return_book)
        self.return_button.pack(pady=5)

        self.add_book_button = tk.Button(self.root, text="添加图书", command=self.add_book)
        self.add_book_button.pack(pady=5)

        # 在主界面显示图书列表
        self.refresh_books_list()

    def refresh_books_list(self):
        self.listbox.delete(0, tk.END)
        for book in self.library.books:
            self.listbox.insert(tk.END, book.display_info())

    def borrow_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.borrow_book(selected_book)
            messagebox.showinfo("借阅图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("借阅图书", "请选择要借阅的图书。")

    def return_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.return_book(selected_book)
            messagebox.showinfo("归还图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("归还图书", "请选择要归还的图书。")

    def add_book(self):
        title_author = simpledialog.askstring("添加图书", "请输入书名和作者(用逗号分隔):")
        if title_author:
            title, author = map(str.strip, title_author.split(','))
            new_book = Book(title, author)
            self.library.books.append(new_book)
            messagebox.showinfo("添加图书", f"《{title}》已成功添加到图书馆。")
            self.refresh_books_list()
    
    def on_closing(self):
        # 保存数据并关闭窗口
        print(f"close main window...")
        self.library.save_data_to_files()

        #self.root.destroy()
        self.root.withdraw()
        self.login_root.deiconify()


class Library:
    def __init__(self):
        self.books = []
        self.users = []
        self.current_user = None

        # 从文件加载图书信息
        self.load_books_from_file()

        # 从文件加载用户信息
        self.load_users_from_file()

    def load_books_from_file(self):
        try:
            with open("books.json", "r") as file:
                books_data = json.load(file)
                for book_data in books_data:
                    book = Book(book_data["title"], book_data["author"])
                    book.is_checked_out = book_data["is_checked_out"]
                    self.books.append(book)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def load_users_from_file(self):
        try:
            with open("users.json", "r") as file:
                users_data = json.load(file)
                for user_data in users_data:
                    user = User(user_data["username"], user_data["password"])
                    user.borrowed_books = [Book(book_data["title"], book_data["author"]) for book_data in user_data["borrowed_books"]]
                    self.users.append(user)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def save_books_to_file(self):
        with open("books.json", "w") as file:
            books_data = []
            for book in self.books:
                book_data = {
                    "title": book.title,
                    "author": book.author,
                    "is_checked_out": book.is_checked_out,
                }
                books_data.append(book_data)
            json.dump(books_data, file, indent=2)

    def save_users_to_file(self):
        with open("users.json", "w") as file:
            users_data = []
            for user in self.users:
                user_data = {
                    "username": user.username,
                    "password": user.password,
                    "borrowed_books": [{"title": book.title, "author": book.author} for book in user.borrowed_books],
                }
                users_data.append(user_data)
            json.dump(users_data, file, indent=2)

    def save_data_to_files(self):
        self.save_books_to_file()
        self.save_users_to_file()

    def find_user(self, username, password):
        for user in self.users:
            if user.username == username and user.password == password:
                self.current_user = user
                return user
        return None

    def is_username_taken(self, username):
        for user in self.users:
            if user.username == username:
                return True
        return False
    
# 创建根窗口并运行程序
root = tk.Tk()
app = LibraryApp(root)

root.mainloop()

books.json 和users.json模板文件

users.json模板文件:

[
  {
    "username": "yli",
    "password": "123",
    "borrowed_books": [
      {
        "title": "To Kill a Mockingbird",
        "author": "Harper Lee"
      }
    ]
  },
  {
    "username": "pipi",
    "password": "456",
    "borrowed_books": []
  }
]

books模板文件:

[
  {
    "title": "The Great Gatsby",
    "author": "F. Scott Fitzgerald",
    "is_checked_out": false
  },
  {
    "title": "To Kill a Mockingbird",
    "author": "Harper Lee",
    "is_checked_out": true
  },
  {
    "title": "1984",
    "author": "George Orwell",
    "is_checked_out": false
  },
  {
    "title": "2024",
    "author": "Michael Li",
    "is_checked_out": false
  },
  {
    "title": "back to 1988",
    "author": "X-Man",
    "is_checked_out": false
  }
]

请输入图片描述

增加登录界面
不幸的是这个程序没有达到预期,
'''
ver12.py: 增加登录界面,登录成功之后再显示主界面
'''

import json
import tkinter as tk
from tkinter import messagebox, simpledialog

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_checked_out = False

    def display_info(self):
        status = "已借出" if self.is_checked_out else "可借阅"
        return f"《{self.title}》 - 作者: {self.author} - 状态: {status}"

    def check_out(self):
        self.is_checked_out = True

    def check_in(self):
        self.is_checked_out = False

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            return f"借阅成功:《{book.title}》"
        else:
            return "抱歉,这本书已经被借出了。"

    def return_book(self, book):
        if book in self.borrowed_books:
            book.check_in()
            self.borrowed_books.remove(book)
            return f"归还成功:《{book.title}》"
        else:
            return "这本书没有被这位用户借阅。"

class LoginApp:
    def __init__(self, root, library_app):
        self.root = root
        self.root.title("用户登录")

        self.library_app = library_app

        # 创建 GUI 元素
        self.label = tk.Label(root, text="用户登录", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.username_label = tk.Label(root, text="用户名:")
        self.username_label.pack()
        self.username_entry = tk.Entry(root)
        self.username_entry.pack(pady=5)

        self.password_label = tk.Label(root, text="密码:")
        self.password_label.pack()
        self.password_entry = tk.Entry(root, show="*")
        self.password_entry.pack(pady=10)

        self.login_button = tk.Button(root, text="登录", command=self.login)
        self.login_button.pack(pady=5)

        self.register_button = tk.Button(root, text="注册", command=self.register)
        self.register_button.pack(pady=5)

    def login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        user = self.library_app.library.find_user(username, password)
        if user:
            # 登录成功,关闭登录窗口并打开主界面窗口
            self.root.destroy()
            self.library_app.show_main_interface(user)
        else:
            messagebox.showwarning("登录失败", "用户名或密码错误。")

    def register(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        if not self.library_app.library.is_username_taken(username):
            new_user = User(username, password)
            self.library_app.library.users.append(new_user)
            messagebox.showinfo("注册成功", "注册成功,请使用新账户登录。")
        else:
            messagebox.showwarning("注册失败", "用户名已被使用,请选择其他用户名。")

class LibraryApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆管理系统")

        self.library = Library()

        # 创建 GUI 元素
        self.label = tk.Label(root, text="欢迎使用图书馆管理系统", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, font=("Helvetica", 12), height=10, width=50)
        self.listbox.pack(pady=10)

        self.borrow_button = tk.Button(root, text="借阅图书", command=self.borrow_book)
        self.borrow_button.pack(pady=5)

        self.return_button = tk.Button(root, text="归还图书", command=self.return_book)
        self.return_button.pack(pady=5)

        self.add_book_button = tk.Button(root, text="添加图书", command=self.add_book)
        self.add_book_button.pack(pady=5)

        # 初始化用户登录界面
        login_root = tk.Toplevel(root)
        self.login_app = LoginApp(login_root, self)

    def show_main_interface(self, user):
        # 在主界面显示欢迎信息
        self.label.config(text=f"欢迎,{user.username}!")

        # 刷新图书列表
        self.refresh_books_list()

        # 显示主界面
        self.root.deiconify()

    def refresh_books_list(self):
        self.listbox.delete(0, tk.END)
        for book in self.library.books:
            self.listbox.insert(tk.END, book.display_info())

    def borrow_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.borrow_book(selected_book)
            messagebox.showinfo("借阅图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("借阅图书", "请选择要借阅的图书。")

    def return_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.return_book(selected_book)
            messagebox.showinfo("归还图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("归还图书", "请选择要归还的图书。")

    def add_book(self):
        title_author = simpledialog.askstring("添加图书", "请输入书名和作者(用逗号分隔):")
        if title_author:
            title, author = map(str.strip, title_author.split(','))
            new_book = Book(title, author)
            self.library.books.append(new_book)
            messagebox.showinfo("添加图书", f"《{title}》已成功添加到图书馆。")
            self.refresh_books_list()

class Library:
    def __init__(self):
        self.books = []
        self.users = []
        self.current_user = None

        # 从文件加载图书信息
        self.load_books_from_file()

        # 从文件加载用户信息
        self.load_users_from_file()

    def load_books_from_file(self):
        try:
            with open("books.json", "r") as file:
                books_data = json.load(file)
                for book_data in books_data:
                    book = Book(book_data["title"], book_data["author"])
                    book.is_checked_out = book_data["is_checked_out"]
                    self.books.append(book)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def load_users_from_file(self):
        try:
            with open("users.json", "r") as file:
                users_data = json.load(file)
                for user_data in users_data:
                    user = User(user_data["username"], user_data["password"])
                    user.borrowed_books = [Book(book_data["title"], book_data["author"]) for book_data in user_data["borrowed_books"]]
                    self.users.append(user)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def save_books_to_file(self):
        with open("books.json", "w") as file:
            books_data = []
            for book in self.books:
                book_data = {
                    "title": book.title,
                    "author": book.author,
                    "is_checked_out": book.is_checked_out,
                }
                books_data.append(book_data)
            json.dump(books_data, file, indent=2)

    def save_users_to_file(self):
        with open("users.json", "w") as file:
            users_data = []
            for user in self.users:
                user_data = {
                    "username": user.username,
                    "password": user.password,
                    "borrowed_books": [{"title": book.title, "author": book.author} for book in user.borrowed_books],
                }
                users_data.append(user_data)
            json.dump(users_data, file, indent=2)

    def save_data_to_files(self):
        self.save_books_to_file()
        self.save_users_to_file()

    def find_user(self, username, password):
        for user in self.users:
            if user.username == username and user.password == password:
                self.current_user = user
                return user
        return None

    def is_username_taken(self, username):
        for user in self.users:
            if user.username == username:
                return True
        return False

# 创建根窗口并运行程序
root = tk.Tk()
app = LibraryApp(root)
root.mainloop()

请输入图片描述

命令行版本的例子,我们会在程序退出的时候保存程序的数据,对于GUI程序,我们也可以在关闭窗口的时候保存这些历史数据,下次运行再次从文件加载
'''
ver11.py: 程序退出的时候保存user 和 book信息
'''
import json
import tkinter as tk
from tkinter import messagebox, simpledialog

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_checked_out = False

    def display_info(self):
        status = "已借出" if self.is_checked_out else "可借阅"
        return f"《{self.title}》 - 作者: {self.author} - 状态: {status}"

    def check_out(self):
        self.is_checked_out = True

    def check_in(self):
        self.is_checked_out = False

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            return f"借阅成功:《{book.title}》"
        else:
            return "抱歉,这本书已经被借出了。"

    def return_book(self, book):
        if book in self.borrowed_books:
            book.check_in()
            self.borrowed_books.remove(book)
            return f"归还成功:《{book.title}》"
        else:
            return "这本书没有被这位用户借阅。"

class LibraryApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆管理系统")

        self.library = Library()

        # 创建 GUI 元素
        self.label = tk.Label(root, text="欢迎使用图书馆管理系统", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, font=("Helvetica", 12), height=10, width=50)
        self.listbox.pack(pady=10)

        self.refresh_books_list()

        self.borrow_button = tk.Button(root, text="借阅图书", command=self.borrow_book)
        self.borrow_button.pack(pady=5)

        self.return_button = tk.Button(root, text="归还图书", command=self.return_book)
        self.return_button.pack(pady=5)

        self.add_book_button = tk.Button(root, text="添加图书", command=self.add_book)
        self.add_book_button.pack(pady=5)

        # 关闭窗口时触发保存数据操作
        root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def refresh_books_list(self):
        self.listbox.delete(0, tk.END)
        for book in self.library.books:
            self.listbox.insert(tk.END, book.display_info())

    def borrow_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.borrow_book(selected_book)
            messagebox.showinfo("借阅图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("借阅图书", "请选择要借阅的图书。")

    def return_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.return_book(selected_book)
            messagebox.showinfo("归还图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("归还图书", "请选择要归还的图书。")

    def add_book(self):
        title_author = simpledialog.askstring("添加图书", "请输入书名和作者(用逗号分隔):")
        if title_author:
            title, author = map(str.strip, title_author.split(','))
            new_book = Book(title, author)
            self.library.books.append(new_book)
            messagebox.showinfo("添加图书", f"《{title}》已成功添加到图书馆。")
            self.refresh_books_list()

    def on_closing(self):
        # 保存数据并关闭窗口
        self.library.save_data_to_files()
        self.root.destroy()

class Library:
    def __init__(self):
        self.books = []
        self.users = []
        self.current_user = User("Guest", "")

        # 从文件加载图书信息
        self.load_books_from_file()

        # 从文件加载用户信息
        self.load_users_from_file()

    def load_books_from_file(self):
        try:
            with open("books.json", "r") as file:
                books_data = json.load(file)
                for book_data in books_data:
                    book = Book(book_data["title"], book_data["author"])
                    book.is_checked_out = book_data["is_checked_out"]
                    self.books.append(book)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def load_users_from_file(self):
        try:
            with open("users.json", "r") as file:
                users_data = json.load(file)
                for user_data in users_data:
                    user = User(user_data["username"], user_data["password"])
                    user.borrowed_books = [Book(book_data["title"], book_data["author"]) for book_data in user_data["borrowed_books"]]
                    self.users.append(user)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def save_books_to_file(self):
        with open("books.json", "w") as file:
            books_data = []
            for book in self.books:
                book_data = {
                    "title": book.title,
                    "author": book.author,
                    "is_checked_out": book.is_checked_out,
                }
                books_data.append(book_data)
            json.dump(books_data, file, indent=2)

    def save_users_to_file(self):
        with open("users.json", "w") as file:
            users_data = []
            for user in self.users:
                user_data = {
                    "username": user.username,
                    "password": user.password,
                    "borrowed_books": [{"title": book.title, "author": book.author} for book in user.borrowed_books],
                }
                users_data.append(user_data)
            json.dump(users_data, file, indent=2)

    def save_data_to_files(self):
        self.save_books_to_file()
        self.save_users_to_file()

# 创建根窗口并运行程序
root = tk.Tk()
app = LibraryApp(root)
root.mainloop()

请输入图片描述

前面例子,新增图书,将作者和书名分成两个独立的对话框输入,比较麻烦,这里尝试组合在一起,使用一个对话框,不过做法貌似不是太好,一定要使用逗号隔开两个字段
'''
ver10.py: 添加图书界面使用一个对话框完成
'''
import json
import tkinter as tk
from tkinter import messagebox, simpledialog

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_checked_out = False

    def display_info(self):
        status = "已借出" if self.is_checked_out else "可借阅"
        return f"《{self.title}》 - 作者: {self.author} - 状态: {status}"

    def check_out(self):
        self.is_checked_out = True

    def check_in(self):
        self.is_checked_out = False

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            return f"借阅成功:《{book.title}》"
        else:
            return "抱歉,这本书已经被借出了。"

    def return_book(self, book):
        if book in self.borrowed_books:
            book.check_in()
            self.borrowed_books.remove(book)
            return f"归还成功:《{book.title}》"
        else:
            return "这本书没有被这位用户借阅。"

class LibraryApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆管理系统")

        self.library = Library()

        # 创建 GUI 元素
        self.label = tk.Label(root, text="欢迎使用图书馆管理系统", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, font=("Helvetica", 12), height=10, width=50)
        self.listbox.pack(pady=10)

        self.refresh_books_list()

        self.borrow_button = tk.Button(root, text="借阅图书", command=self.borrow_book)
        self.borrow_button.pack(pady=5)

        self.return_button = tk.Button(root, text="归还图书", command=self.return_book)
        self.return_button.pack(pady=5)

        self.add_book_button = tk.Button(root, text="添加图书", command=self.add_book)
        self.add_book_button.pack(pady=5)

    def refresh_books_list(self):
        self.listbox.delete(0, tk.END)
        for book in self.library.books:
            self.listbox.insert(tk.END, book.display_info())

    def borrow_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.borrow_book(selected_book)
            messagebox.showinfo("借阅图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("借阅图书", "请选择要借阅的图书。")

    def return_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.return_book(selected_book)
            messagebox.showinfo("归还图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("归还图书", "请选择要归还的图书。")

    def add_book(self):
        title_author = simpledialog.askstring("添加图书", "请输入书名和作者(用逗号分隔):")
        if title_author:
            title, author = map(str.strip, title_author.split(','))
            new_book = Book(title, author)
            self.library.books.append(new_book)
            messagebox.showinfo("添加图书", f"《{title}》已成功添加到图书馆。")
            self.refresh_books_list()

class Library:
    def __init__(self):
        self.books = []
        self.users = []
        self.current_user = User("Guest", "")

        # 从文件加载图书信息
        self.load_books_from_file()

        # 从文件加载用户信息
        self.load_users_from_file()

    def load_books_from_file(self):
        try:
            with open("books.json", "r") as file:
                books_data = json.load(file)
                for book_data in books_data:
                    book = Book(book_data["title"], book_data["author"])
                    book.is_checked_out = book_data["is_checked_out"]
                    self.books.append(book)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def load_users_from_file(self):
        try:
            with open("users.json", "r") as file:
                users_data = json.load(file)
                for user_data in users_data:
                    user = User(user_data["username"], user_data["password"])
                    user.borrowed_books = [Book(book_data["title"], book_data["author"]) for book_data in user_data["borrowed_books"]]
                    self.users.append(user)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def save_books_to_file(self):
        with open("books.json", "w") as file:
            books_data = []
            for book in self.books:
                book_data = {
                    "title": book.title,
                    "author": book.author,
                    "is_checked_out": book.is_checked_out,
                }
                books_data.append(book_data)
            json.dump(books_data, file, indent=2)

    def save_users_to_file(self):
        with open("users.json", "w") as file:
            users_data = []
            for user in self.users:
                user_data = {
                    "username": user.username,
                    "password": user.password,
                    "borrowed_books": [{"title": book.title, "author": book.author} for book in user.borrowed_books],
                }
                users_data.append(user_data)
            json.dump(users_data, file, indent=2)

# 创建根窗口并运行程序
root = tk.Tk()
app = LibraryApp(root)
root.mainloop()

请输入图片描述

前面的程序都是运行在终端,现代程序都有漂亮的人机界面-GUI 图形用户界面,这里我们尝试用图形库改写前面的例子,这里选秀用Tkiner,比较简单,好上手
这个界面只是显示默认图书列表,让用户可以选择借阅或者归还,没有用户登录界面,后面继续补上
'''
ver9.py: 使用GUI,tkinter
'''
import json
import tkinter as tk
from tkinter import messagebox, simpledialog

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_checked_out = False

    def display_info(self):
        status = "已借出" if self.is_checked_out else "可借阅"
        return f"《{self.title}》 - 作者: {self.author} - 状态: {status}"

    def check_out(self):
        self.is_checked_out = True

    def check_in(self):
        self.is_checked_out = False

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.borrowed_books = []

    def borrow_book(self, book):
        if not book.is_checked_out:
            book.check_out()
            self.borrowed_books.append(book)
            return f"借阅成功:《{book.title}》"
        else:
            return "抱歉,这本书已经被借出了。"

    def return_book(self, book):
        if book in self.borrowed_books:
            book.check_in()
            self.borrowed_books.remove(book)
            return f"归还成功:《{book.title}》"
        else:
            return "这本书没有被这位用户借阅。"

class LibraryApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图书馆管理系统")

        self.library = Library()

        # 创建 GUI 元素
        self.label = tk.Label(root, text="欢迎使用图书馆管理系统", font=("Helvetica", 16))
        self.label.pack(pady=10)

        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, font=("Helvetica", 12), height=10, width=50)
        self.listbox.pack(pady=10)

        self.refresh_books_list()

        self.borrow_button = tk.Button(root, text="借阅图书", command=self.borrow_book)
        self.borrow_button.pack(pady=5)

        self.return_button = tk.Button(root, text="归还图书", command=self.return_book)
        self.return_button.pack(pady=5)

        self.add_book_button = tk.Button(root, text="添加图书", command=self.add_book)
        self.add_book_button.pack(pady=5)

    def refresh_books_list(self):
        self.listbox.delete(0, tk.END)
        for book in self.library.books:
            self.listbox.insert(tk.END, book.display_info())

    def borrow_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.borrow_book(selected_book)
            messagebox.showinfo("借阅图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("借阅图书", "请选择要借阅的图书。")

    def return_book(self):
        selected_index = self.listbox.curselection()
        if selected_index:
            selected_book = self.library.books[selected_index[0]]
            message = self.library.current_user.return_book(selected_book)
            messagebox.showinfo("归还图书", message)
            self.refresh_books_list()
        else:
            messagebox.showwarning("归还图书", "请选择要归还的图书。")

    def add_book(self):
        title = simpledialog.askstring("添加图书", "请输入书名:")
        author = simpledialog.askstring("添加图书", "请输入作者:")
        if title and author:
            new_book = Book(title, author)
            self.library.books.append(new_book)
            messagebox.showinfo("添加图书", f"《{title}》已成功添加到图书馆。")
            self.refresh_books_list()

class Library:
    def __init__(self):
        self.books = []
        self.users = []
        self.current_user = User("Guest", "")

        # 从文件加载图书信息
        self.load_books_from_file()

        # 从文件加载用户信息
        self.load_users_from_file()

    def load_books_from_file(self):
        try:
            with open("books.json", "r") as file:
                books_data = json.load(file)
                for book_data in books_data:
                    book = Book(book_data["title"], book_data["author"])
                    book.is_checked_out = book_data["is_checked_out"]
                    self.books.append(book)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def load_users_from_file(self):
        try:
            with open("users.json", "r") as file:
                users_data = json.load(file)
                for user_data in users_data:
                    user = User(user_data["username"], user_data["password"])
                    user.borrowed_books = [Book(book_data["title"], book_data["author"]) for book_data in user_data["borrowed_books"]]
                    self.users.append(user)
        except FileNotFoundError:
            # 文件不存在,可能是第一次运行程序
            pass

    def save_books_to_file(self):
        with open("books.json", "w") as file:
            books_data = []
            for book in self.books:
                book_data = {
                    "title": book.title,
                    "author": book.author,
                    "is_checked_out": book.is_checked_out,
                }
                books_data.append(book_data)
            json.dump(books_data, file, indent=2)

    def save_users_to_file(self):
        with open("users.json", "w") as file:
            users_data = []
            for user in self.users:
                user_data = {
                    "username": user.username,
                    "password": user.password,
                    "borrowed_books": [{"title": book.title, "author": book.author} for book in user.borrowed_books],
                }
                users_data.append(user_data)
            json.dump(users_data, file, indent=2)

# 创建根窗口并运行程序
root = tk.Tk()
app = LibraryApp(root)
root.mainloop()