Менеджер коллекций c локальной базой данных.
Цитата: Kiya229 от 16.07.2023, 00:40Техническое задание
Цель: Создать программу "Менеджер коллекций", которая позволит пользователям создавать и управлять коллекциями заметок.
Описание функциональности:
Создание пользователя:
- Пользователь может ввести имя нового пользователя в поле ввода.
- При нажатии на кнопку "Создать пользователя" происходит проверка наличия пользователя с таким именем в базе данных.
- Если пользователь с таким именем уже существует, появляется предупреждающее сообщение об ошибке.
- Если пользователь с таким именем не существует, он создается в базе данных, и его имя добавляется в список пользователей в GUI.
- Поле ввода очищается после создания пользователя.
Выбор пользователя:
- Пользователь может выбрать одного из имеющихся в списке пользователей для входа в его аккаунт.
- При выборе пользователя происходит скрытие основного окна и открытие окна с коллекциями выбранного пользователя.
Удаление пользователя:
- Пользователь может выбрать одного из имеющихся в списке пользователей для удаления его аккаунта.
- При выборе пользователя появляется запрос на подтверждение удаления пользователя.
- Если пользователь подтверждает удаление, его данные удаляются из базы данных, и его имя удаляется из списка пользователей в GUI.
Создание коллекции:
- В окне с коллекциями пользователь может создать новую коллекцию заметок.
- Пользователь вводит название новой коллекции в соответствующее поле ввода и текст заметки вместе с названием коллекции.
- При нажатии на кнопку "Создать коллекцию" происходит проверка правильности ввода.
- Если формат ввода корректен (название коллекции начинается с символа "#", а после названия идет текст заметки), коллекция и заметка сохраняются в базе данных.
- Новая коллекция отображается в списке коллекций пользователя.
Удаление коллекции:
- В окне с коллекциями пользователь может выбрать одну из коллекций для удаления.
- При выборе коллекции появляется запрос на подтверждение удаления коллекции.
- Если пользователь подтверждает удаление, коллекция и все связанные с ней заметки удаляются из базы данных.
Отображение заметок:
- В окне с коллекциями пользователь может выбрать одну из коллекций для просмотра заметок.
- При выборе коллекции происходит скрытие окна с коллекциями и открытие окна со списком заметок выбранной коллекции.
- Заметки отображаются в виде списка внутри окна со скроллбаром.
Создание заметки:
- В окне со списком заметок пользователь может создать новую заметку.
- Пользователь вводит текст заметки в соответствующее поле ввода.
- При нажатии на кнопку "Создать заметку" новая заметка сохраняется в базе данных и отображается в списке заметок.
Удаление заметки:
- В окне со списком заметок пользователь может выбрать одну из заметок для удаления.
- При выборе заметки появляется запрос на подтверждение удаления заметки.
- Если пользователь подтверждает удаление, заметка удаляется из базы данных и из списка заметок.
Описание пользовательского интерфейса:
Основное окно:
- Заголовок: "Менеджер коллекций"
- Размер: 140x240
- Поле ввода имени пользователя
- Кнопка "Создать пользователя"
- Список пользователей
- Кнопка "Войти"
- Кнопка "Удалить"
Окно с коллекциями:
- Заголовок: "Коллекции"
- Размер: 634x664
- Фрейм для списка коллекций с прокруткой
- Фрейм для кнопок и поля ввода
- Скроллбар для списка коллекций
- Список коллекций
- Поле ввода названия новой коллекции
- Кнопка "Создать коллекцию"
- Кнопка "Удалить коллекцию"
- Кнопка "Вернуться"
Окно со списком заметок:
- Заголовок: Название выбранной коллекции
- Размер: 634x664
- Фрейм для списка заметок с прокруткой
- Фрейм для кнопок
- Скроллбар для списка заметок
- Список заметок
- Кнопка "Удалить заметку"
- Кнопка "Вернуться"
При сворачивании или закрытии программы, она уходит в трей.
Нужно доработать интерфейс, отключить разворачивание окна.
Внизу приведён примерный интерфейс.
Текущий код плохо сохраняет заметки[spoiler title="Примерный недоработанный код Python"]
import tkinter as tk from tkinter import messagebox import sqlite3 # Создание базы данных и таблицы conn = sqlite3.connect('collections.db') c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS users (username TEXT PRIMARY KEY)''') c.execute('''CREATE TABLE IF NOT EXISTS notes (username TEXT, collection TEXT, note TEXT)''') conn.commit() # Функция для создания нового пользователя def create_user(): new_user = input_username.get().strip() if new_user: c.execute("SELECT * FROM users WHERE username=?", (new_user,)) existing_user = c.fetchone() if existing_user: messagebox.showwarning("Ошибка", "Пользователь уже существует") else: c.execute("INSERT INTO users VALUES (?)", (new_user,)) conn.commit() list_collections.insert(tk.END, new_user) # Добавляем нового пользователя в список input_username.delete(0, tk.END) # Очистка поля ввода имени пользователя # Функция для обработки события выбора пользователя def select_user(): selected_user = list_collections.get(tk.ACTIVE) if selected_user: root.withdraw() # Скрываем основное окно show_collections_window(selected_user) # Отображаем окно с коллекциями # Функция для удаления выбранного пользователя def delete_user(): selected_user = list_collections.get(tk.ACTIVE) if selected_user: confirmed = messagebox.askyesno("Удаление пользователя", "Вы действительно хотите удалить пользователя?") if confirmed: c.execute("DELETE FROM users WHERE username=?", (selected_user,)) c.execute("DELETE FROM notes WHERE username=?", (selected_user,)) conn.commit() list_collections.delete(tk.ACTIVE) # Удаляем выбранного пользователя из списка # Функция для отображения окна с коллекциями пользователя def show_collections_window(username): collections_window = tk.Toplevel() collections_window.title("Коллекции") collections_window.geometry("634x664") # Фрейм для списка коллекций с прокруткой collections_frame = tk.Frame(collections_window) collections_frame.pack(pady=10) # Фрейм для кнопок и поля ввода button_frame = tk.Frame(collections_window) button_frame.pack(pady=10) # Прокрутка списка коллекций scrollbar = tk.Scrollbar(collections_frame) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # Список коллекций list_collections = tk.Listbox(collections_frame, yscrollcommand=scrollbar.set) list_collections.pack(side=tk.LEFT, fill=tk.BOTH) # Привязываем прокрутку к списку коллекций scrollbar.config(command=list_collections.yview) # Функция для обработки события выбора коллекции def select_collection(event): selected_collection = list_collections.get(tk.ACTIVE) if selected_collection: collections_window.withdraw() # Скрываем окно с коллекциями show_notes_window(username, selected_collection) # Отображаем окно с заметками # Привязываем обработчик события выбора коллекции list_collections.bind('<<ListboxSelect>>', select_collection) # Загружаем список коллекций пользователя из базы данных c.execute("SELECT collection FROM notes WHERE username=? AND collection LIKE ?", (username, f"{username}%",)) collections = c.fetchall() for collection in collections: list_collections.insert(tk.END, collection[0]) # Функция для создания новой коллекции def create_collection(): new_collection_text = input_new_collection.get().strip().split(' ') if len(new_collection_text) > 1 and new_collection_text[0].startswith('#'): new_collection = new_collection_text[0][1:] note = ' '.join(new_collection_text[1:]) c.execute("INSERT INTO notes VALUES (?, ?, ?)", (username, new_collection, note)) conn.commit() list_collections.insert(tk.END, new_collection) else: messagebox.showwarning("Ошибка", "Некорректный формат коллекции и заметки") # Поле ввода названия новой коллекции input_new_collection = tk.Entry(button_frame) input_new_collection.pack(side=tk.LEFT) btn_create_collection = tk.Button(button_frame, text="Создать коллекцию", command=create_collection) btn_create_collection.pack(side=tk.LEFT, padx=10) # Функция для удаления выбранной коллекции def delete_collection(): selected_collection = list_collections.get(tk.ACTIVE) if selected_collection: confirmed = messagebox.askyesno("Удаление коллекции", "Вы действительно хотите удалить коллекцию?") if confirmed: c.execute("DELETE FROM notes WHERE username=? AND collection=?", (username, selected_collection)) conn.commit() list_collections.delete(tk.ACTIVE) # Кнопка для удаления коллекции btn_delete_collection = tk.Button(button_frame, text="Удалить коллекцию", command=delete_collection) btn_delete_collection.pack(side=tk.LEFT) # Функция для возврата в основное окно def return_to_main(): collections_window.destroy() root.deiconify() # Восстанавливаем основное окно # Кнопка для возврата в основное окно btn_return = tk.Button(collections_window, text="Вернуться", command=return_to_main) btn_return.pack() collections_window.protocol("WM_DELETE_WINDOW", return_to_main) # Функция для отображения окна с заметками по выбранной коллекции def show_notes_window(username, collection): notes_window = tk.Toplevel() notes_window.title(collection) notes_window.geometry("634x664") # Фрейм для списка заметок с прокруткой notes_frame = tk.Frame(notes_window) notes_frame.pack(pady=10) # Фрейм для кнопок button_frame = tk.Frame(notes_window) button_frame.pack(pady=10) # Прокрутка списка заметок scrollbar = tk.Scrollbar(notes_frame) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # Список заметок list_notes = tk.Listbox(notes_frame, yscrollcommand=scrollbar.set) list_notes.pack(side=tk.LEFT, fill=tk.BOTH) # Привязываем прокрутку к списку заметок scrollbar.config(command=list_notes.yview) # Загружаем заметки по выбранной коллекции из базы данных c.execute("SELECT note FROM notes WHERE username=? AND collection=?", (username, collection)) notes = c.fetchall() for note in notes: list_notes.insert(tk.END, note[0]) # Функция для удаления выбранной заметки def delete_note(): selected_note = list_notes.get(tk.ACTIVE) if selected_note: confirmed = messagebox.askyesno("Удаление заметки", "Вы действительно хотите удалить заметку?") if confirmed: c.execute("DELETE FROM notes WHERE username=? AND collection=? AND note=?", (username, collection, selected_note)) conn.commit() list_notes.delete(tk.ACTIVE) # Кнопка для удаления заметки btn_delete_note = tk.Button(button_frame, text="Удалить заметку", command=delete_note) btn_delete_note.pack(side=tk.LEFT) # Функция для возврата к списку коллекций def return_to_collections(): notes_window.destroy() root.deiconify() # Восстанавливаем основное окно # Кнопка для возврата к списку коллекций btn_return = tk.Button(button_frame, text="Вернуться", command=return_to_collections) btn_return.pack(side=tk.LEFT) notes_window.protocol("WM_DELETE_WINDOW", return_to_collections) # Окно приложения root = tk.Tk() root.title("Менеджер коллекций") root.geometry("140x240") # Задаем ширину и высоту окна # Поле ввода имени пользователя и кнопка "Создать пользователя" input_username = tk.Entry(root) input_username.pack() btn_create_user = tk.Button(root, text="Создать пользователя", command=create_user) btn_create_user.pack() # Фрейм для кнопок "Войти" и "Удалить" button_frame = tk.Frame(root) button_frame.pack(pady=10) btn_select_user = tk.Button(button_frame, text="Войти", command=select_user) btn_select_user.pack(side=tk.LEFT, padx=10) btn_delete_user = tk.Button(button_frame, text="Удалить", command=delete_user) btn_delete_user.pack(side=tk.LEFT, padx=10) # Список коллекций list_collections = tk.Listbox(root) list_collections.pack() # Загружаем список пользователей из базы данных c.execute("SELECT * FROM users") users = c.fetchall() for user in users: list_collections.insert(tk.END, user[0]) root.mainloop() # Закрываем соединение с базой данных при выходе из программы conn.close()[/spoiler][spoiler title="Ссылки для скачивания"]Скачать .exe Скачать .py icon[/spoiler]
[spoiler title="Как видит моя больная фантазия интерфейс"]
[/spoiler]
Техническое задание
Цель: Создать программу "Менеджер коллекций", которая позволит пользователям создавать и управлять коллекциями заметок.
Описание функциональности:
-
Создание пользователя:
- Пользователь может ввести имя нового пользователя в поле ввода.
- При нажатии на кнопку "Создать пользователя" происходит проверка наличия пользователя с таким именем в базе данных.
- Если пользователь с таким именем уже существует, появляется предупреждающее сообщение об ошибке.
- Если пользователь с таким именем не существует, он создается в базе данных, и его имя добавляется в список пользователей в GUI.
- Поле ввода очищается после создания пользователя.
-
Выбор пользователя:
- Пользователь может выбрать одного из имеющихся в списке пользователей для входа в его аккаунт.
- При выборе пользователя происходит скрытие основного окна и открытие окна с коллекциями выбранного пользователя.
-
Удаление пользователя:
- Пользователь может выбрать одного из имеющихся в списке пользователей для удаления его аккаунта.
- При выборе пользователя появляется запрос на подтверждение удаления пользователя.
- Если пользователь подтверждает удаление, его данные удаляются из базы данных, и его имя удаляется из списка пользователей в GUI.
-
Создание коллекции:
- В окне с коллекциями пользователь может создать новую коллекцию заметок.
- Пользователь вводит название новой коллекции в соответствующее поле ввода и текст заметки вместе с названием коллекции.
- При нажатии на кнопку "Создать коллекцию" происходит проверка правильности ввода.
- Если формат ввода корректен (название коллекции начинается с символа "#", а после названия идет текст заметки), коллекция и заметка сохраняются в базе данных.
- Новая коллекция отображается в списке коллекций пользователя.
-
Удаление коллекции:
- В окне с коллекциями пользователь может выбрать одну из коллекций для удаления.
- При выборе коллекции появляется запрос на подтверждение удаления коллекции.
- Если пользователь подтверждает удаление, коллекция и все связанные с ней заметки удаляются из базы данных.
-
Отображение заметок:
- В окне с коллекциями пользователь может выбрать одну из коллекций для просмотра заметок.
- При выборе коллекции происходит скрытие окна с коллекциями и открытие окна со списком заметок выбранной коллекции.
- Заметки отображаются в виде списка внутри окна со скроллбаром.
-
Создание заметки:
- В окне со списком заметок пользователь может создать новую заметку.
- Пользователь вводит текст заметки в соответствующее поле ввода.
- При нажатии на кнопку "Создать заметку" новая заметка сохраняется в базе данных и отображается в списке заметок.
-
Удаление заметки:
- В окне со списком заметок пользователь может выбрать одну из заметок для удаления.
- При выборе заметки появляется запрос на подтверждение удаления заметки.
- Если пользователь подтверждает удаление, заметка удаляется из базы данных и из списка заметок.
Описание пользовательского интерфейса:
-
Основное окно:
- Заголовок: "Менеджер коллекций"
- Размер: 140x240
- Поле ввода имени пользователя
- Кнопка "Создать пользователя"
- Список пользователей
- Кнопка "Войти"
- Кнопка "Удалить"
-
Окно с коллекциями:
- Заголовок: "Коллекции"
- Размер: 634x664
- Фрейм для списка коллекций с прокруткой
- Фрейм для кнопок и поля ввода
- Скроллбар для списка коллекций
- Список коллекций
- Поле ввода названия новой коллекции
- Кнопка "Создать коллекцию"
- Кнопка "Удалить коллекцию"
- Кнопка "Вернуться"
-
Окно со списком заметок:
- Заголовок: Название выбранной коллекции
- Размер: 634x664
- Фрейм для списка заметок с прокруткой
- Фрейм для кнопок
- Скроллбар для списка заметок
- Список заметок
- Кнопка "Удалить заметку"
- Кнопка "Вернуться"
При сворачивании или закрытии программы, она уходит в трей.
Нужно доработать интерфейс, отключить разворачивание окна.
Внизу приведён примерный интерфейс.
Текущий код плохо сохраняет заметки
import tkinter as tk
from tkinter import messagebox
import sqlite3
# Создание базы данных и таблицы
conn = sqlite3.connect('collections.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS users
(username TEXT PRIMARY KEY)''')
c.execute('''CREATE TABLE IF NOT EXISTS notes
(username TEXT, collection TEXT, note TEXT)''')
conn.commit()
# Функция для создания нового пользователя
def create_user():
new_user = input_username.get().strip()
if new_user:
c.execute("SELECT * FROM users WHERE username=?", (new_user,))
existing_user = c.fetchone()
if existing_user:
messagebox.showwarning("Ошибка", "Пользователь уже существует")
else:
c.execute("INSERT INTO users VALUES (?)", (new_user,))
conn.commit()
list_collections.insert(tk.END, new_user) # Добавляем нового пользователя в список
input_username.delete(0, tk.END) # Очистка поля ввода имени пользователя
# Функция для обработки события выбора пользователя
def select_user():
selected_user = list_collections.get(tk.ACTIVE)
if selected_user:
root.withdraw() # Скрываем основное окно
show_collections_window(selected_user) # Отображаем окно с коллекциями
# Функция для удаления выбранного пользователя
def delete_user():
selected_user = list_collections.get(tk.ACTIVE)
if selected_user:
confirmed = messagebox.askyesno("Удаление пользователя", "Вы действительно хотите удалить пользователя?")
if confirmed:
c.execute("DELETE FROM users WHERE username=?", (selected_user,))
c.execute("DELETE FROM notes WHERE username=?", (selected_user,))
conn.commit()
list_collections.delete(tk.ACTIVE) # Удаляем выбранного пользователя из списка
# Функция для отображения окна с коллекциями пользователя
def show_collections_window(username):
collections_window = tk.Toplevel()
collections_window.title("Коллекции")
collections_window.geometry("634x664")
# Фрейм для списка коллекций с прокруткой
collections_frame = tk.Frame(collections_window)
collections_frame.pack(pady=10)
# Фрейм для кнопок и поля ввода
button_frame = tk.Frame(collections_window)
button_frame.pack(pady=10)
# Прокрутка списка коллекций
scrollbar = tk.Scrollbar(collections_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# Список коллекций
list_collections = tk.Listbox(collections_frame, yscrollcommand=scrollbar.set)
list_collections.pack(side=tk.LEFT, fill=tk.BOTH)
# Привязываем прокрутку к списку коллекций
scrollbar.config(command=list_collections.yview)
# Функция для обработки события выбора коллекции
def select_collection(event):
selected_collection = list_collections.get(tk.ACTIVE)
if selected_collection:
collections_window.withdraw() # Скрываем окно с коллекциями
show_notes_window(username, selected_collection) # Отображаем окно с заметками
# Привязываем обработчик события выбора коллекции
list_collections.bind('<<ListboxSelect>>', select_collection)
# Загружаем список коллекций пользователя из базы данных
c.execute("SELECT collection FROM notes WHERE username=? AND collection LIKE ?", (username, f"{username}%",))
collections = c.fetchall()
for collection in collections:
list_collections.insert(tk.END, collection[0])
# Функция для создания новой коллекции
def create_collection():
new_collection_text = input_new_collection.get().strip().split(' ')
if len(new_collection_text) > 1 and new_collection_text[0].startswith('#'):
new_collection = new_collection_text[0][1:]
note = ' '.join(new_collection_text[1:])
c.execute("INSERT INTO notes VALUES (?, ?, ?)", (username, new_collection, note))
conn.commit()
list_collections.insert(tk.END, new_collection)
else:
messagebox.showwarning("Ошибка", "Некорректный формат коллекции и заметки")
# Поле ввода названия новой коллекции
input_new_collection = tk.Entry(button_frame)
input_new_collection.pack(side=tk.LEFT)
btn_create_collection = tk.Button(button_frame, text="Создать коллекцию", command=create_collection)
btn_create_collection.pack(side=tk.LEFT, padx=10)
# Функция для удаления выбранной коллекции
def delete_collection():
selected_collection = list_collections.get(tk.ACTIVE)
if selected_collection:
confirmed = messagebox.askyesno("Удаление коллекции", "Вы действительно хотите удалить коллекцию?")
if confirmed:
c.execute("DELETE FROM notes WHERE username=? AND collection=?", (username, selected_collection))
conn.commit()
list_collections.delete(tk.ACTIVE)
# Кнопка для удаления коллекции
btn_delete_collection = tk.Button(button_frame, text="Удалить коллекцию", command=delete_collection)
btn_delete_collection.pack(side=tk.LEFT)
# Функция для возврата в основное окно
def return_to_main():
collections_window.destroy()
root.deiconify() # Восстанавливаем основное окно
# Кнопка для возврата в основное окно
btn_return = tk.Button(collections_window, text="Вернуться", command=return_to_main)
btn_return.pack()
collections_window.protocol("WM_DELETE_WINDOW", return_to_main)
# Функция для отображения окна с заметками по выбранной коллекции
def show_notes_window(username, collection):
notes_window = tk.Toplevel()
notes_window.title(collection)
notes_window.geometry("634x664")
# Фрейм для списка заметок с прокруткой
notes_frame = tk.Frame(notes_window)
notes_frame.pack(pady=10)
# Фрейм для кнопок
button_frame = tk.Frame(notes_window)
button_frame.pack(pady=10)
# Прокрутка списка заметок
scrollbar = tk.Scrollbar(notes_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# Список заметок
list_notes = tk.Listbox(notes_frame, yscrollcommand=scrollbar.set)
list_notes.pack(side=tk.LEFT, fill=tk.BOTH)
# Привязываем прокрутку к списку заметок
scrollbar.config(command=list_notes.yview)
# Загружаем заметки по выбранной коллекции из базы данных
c.execute("SELECT note FROM notes WHERE username=? AND collection=?", (username, collection))
notes = c.fetchall()
for note in notes:
list_notes.insert(tk.END, note[0])
# Функция для удаления выбранной заметки
def delete_note():
selected_note = list_notes.get(tk.ACTIVE)
if selected_note:
confirmed = messagebox.askyesno("Удаление заметки", "Вы действительно хотите удалить заметку?")
if confirmed:
c.execute("DELETE FROM notes WHERE username=? AND collection=? AND note=?", (username, collection, selected_note))
conn.commit()
list_notes.delete(tk.ACTIVE)
# Кнопка для удаления заметки
btn_delete_note = tk.Button(button_frame, text="Удалить заметку", command=delete_note)
btn_delete_note.pack(side=tk.LEFT)
# Функция для возврата к списку коллекций
def return_to_collections():
notes_window.destroy()
root.deiconify() # Восстанавливаем основное окно
# Кнопка для возврата к списку коллекций
btn_return = tk.Button(button_frame, text="Вернуться", command=return_to_collections)
btn_return.pack(side=tk.LEFT)
notes_window.protocol("WM_DELETE_WINDOW", return_to_collections)
# Окно приложения
root = tk.Tk()
root.title("Менеджер коллекций")
root.geometry("140x240") # Задаем ширину и высоту окна
# Поле ввода имени пользователя и кнопка "Создать пользователя"
input_username = tk.Entry(root)
input_username.pack()
btn_create_user = tk.Button(root, text="Создать пользователя", command=create_user)
btn_create_user.pack()
# Фрейм для кнопок "Войти" и "Удалить"
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
btn_select_user = tk.Button(button_frame, text="Войти", command=select_user)
btn_select_user.pack(side=tk.LEFT, padx=10)
btn_delete_user = tk.Button(button_frame, text="Удалить", command=delete_user)
btn_delete_user.pack(side=tk.LEFT, padx=10)
# Список коллекций
list_collections = tk.Listbox(root)
list_collections.pack()
# Загружаем список пользователей из базы данных
c.execute("SELECT * FROM users")
users = c.fetchall()
for user in users:
list_collections.insert(tk.END, user[0])
root.mainloop()
# Закрываем соединение с базой данных при выходе из программы
conn.close()


