/
BaSer
/
BookTracker
Обзор
Документация
Войти
/
BaSer
/
BookTracker
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
main.py
185 строк
8 KB
BaSer
create: .gitignore.txt, books.json, main.py, README.md
05 май 2026, 22:42
Верифицирован
05 май 2026, 22:42
e70d5bf
Код
Авторство
О чём код?
import json import os from tkinter import * from tkinter import ttk, messagebox class BookTracker: def __init__(self, root): self.root = root self.root.title("Book Tracker - Трекер прочитанных книг") self.root.geometry("800x500") self.books = [] self.load_data() # Поля ввода self.create_input_fields() # Таблица книг self.create_treeview() # Фильтры self.create_filters() # Кнопки действий self.create_buttons() self.refresh_table() def create_input_fields(self): frame = LabelFrame(self.root, text="Добавить новую книгу", padx=10, pady=10) frame.pack(fill="x", padx=10, pady=5) Label(frame, text="Название:").grid(row=0, column=0, sticky="w") self.title_entry = Entry(frame, width=30) self.title_entry.grid(row=0, column=1, padx=5, pady=2) Label(frame, text="Автор:").grid(row=0, column=2, sticky="w") self.author_entry = Entry(frame, width=30) self.author_entry.grid(row=0, column=3, padx=5, pady=2) Label(frame, text="Жанр:").grid(row=1, column=0, sticky="w") self.genre_entry = Entry(frame, width=30) self.genre_entry.grid(row=1, column=1, padx=5, pady=2) Label(frame, text="Страниц:").grid(row=1, column=2, sticky="w") self.pages_entry = Entry(frame, width=30) self.pages_entry.grid(row=1, column=3, padx=5, pady=2) def create_treeview(self): frame = Frame(self.root) frame.pack(fill="both", expand=True, padx=10, pady=5) columns = ("Название", "Автор", "Жанр", "Страниц") self.tree = ttk.Treeview(frame, columns=columns, show="headings") for col in columns: self.tree.heading(col, text=col) self.tree.column(col, width=180) scrollbar = ttk.Scrollbar(frame, orient="vertical", command=self.tree.yview) self.tree.configure(yscrollcommand=scrollbar.set) self.tree.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") def create_filters(self): frame = LabelFrame(self.root, text="Фильтрация", padx=10, pady=10) frame.pack(fill="x", padx=10, pady=5) Label(frame, text="Фильтр по жанру:").grid(row=0, column=0, sticky="w") self.filter_genre_entry = Entry(frame, width=20) self.filter_genre_entry.grid(row=0, column=1, padx=5, pady=2) Label(frame, text="Страниц больше:").grid(row=0, column=2, sticky="w") self.filter_pages_entry = Entry(frame, width=10) self.filter_pages_entry.grid(row=0, column=3, padx=5, pady=2) Button(frame, text="Применить фильтр", command=self.apply_filter).grid(row=0, column=4, padx=10) Button(frame, text="Сбросить фильтр", command=self.reset_filter).grid(row=0, column=5) def create_buttons(self): frame = Frame(self.root) frame.pack(fill="x", padx=10, pady=5) Button(frame, text="Добавить книгу", command=self.add_book, bg="lightgreen", width=15).pack(side="left", padx=5) Button(frame, text="Сохранить в JSON", command=self.save_data, bg="lightblue", width=15).pack(side="left", padx=5) Button(frame, text="Загрузить из JSON", command=self.load_data_from_disk, bg="lightyellow", width=15).pack(side="left", padx=5) def add_book(self): title = self.title_entry.get().strip() author = self.author_entry.get().strip() genre = self.genre_entry.get().strip() pages_str = self.pages_entry.get().strip() if not title or not author or not genre or not pages_str: messagebox.showerror("Ошибка", "Все поля должны быть заполнены!") return try: pages = int(pages_str) if pages <= 0: raise ValueError except ValueError: messagebox.showerror("Ошибка", "Количество страниц должно быть положительным числом!") return book = { "title": title, "author": author, "genre": genre, "pages": pages } self.books.append(book) self.refresh_table() self.clear_entries() messagebox.showinfo("Успех", "Книга добавлена!") def refresh_table(self, filtered_books=None): for row in self.tree.get_children(): self.tree.delete(row) data = filtered_books if filtered_books is not None else self.books for book in data: self.tree.insert("", "end", values=(book["title"], book["author"], book["genre"], book["pages"])) def apply_filter(self): genre_filter = self.filter_genre_entry.get().strip().lower() pages_filter = self.filter_pages_entry.get().strip() filtered = self.books[:] if genre_filter: filtered = [b for b in filtered if genre_filter in b["genre"].lower()] if pages_filter: try: pages_threshold = int(pages_filter) filtered = [b for b in filtered if b["pages"] > pages_threshold] except ValueError: messagebox.showerror("Ошибка", "Фильтр страниц должен быть числом!") return self.refresh_table(filtered) def reset_filter(self): self.filter_genre_entry.delete(0, END) self.filter_pages_entry.delete(0, END) self.refresh_table() def clear_entries(self): self.title_entry.delete(0, END) self.author_entry.delete(0, END) self.genre_entry.delete(0, END) self.pages_entry.delete(0, END) def save_data(self): try: with open("books.json", "w", encoding="utf-8") as f: json.dump(self.books, f, ensure_ascii=False, indent=4) messagebox.showinfo("Успех", "Данные сохранены в books.json") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось сохранить: {e}") def load_data_from_disk(self): if os.path.exists("books.json"): try: with open("books.json", "r", encoding="utf-8") as f: self.books = json.load(f) self.refresh_table() messagebox.showinfo("Успех", "Данные загружены из books.json") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось загрузить: {e}") else: messagebox.showwarning("Нет файла", "Файл books.json не найден") def load_data(self): if os.path.exists("books.json"): with open("books.json", "r", encoding="utf-8") as f: self.books = json.load(f) if __name__ == "__main__": root = Tk() app = BookTracker(root) root.mainloop()