Швидкі Нотатки
- Ціна
- 40 ₴
- Автор
- Denys 2026
- Категорія
- Інше
Опис
import tkinter as tk
import json
import os
DATA_FILE = "app_data.json"
class NotesApp:
def init(self, root):
self.root = root
self.root.title("Нотатки")
self.root.geometry("380x680")
self.root.configure(bg="#121212")
self.lang = "uk"
self.account = None
self.notes = []
self.current_hour = 0
self.current_minute = 0
self.translations = {
"uk": {
"title": "НОТАТКИ",
"login_btn": "УВІЙТИ ЧЕРЕЗ ГУГЛ",
"choose_acc": "Оберіть обліковий запис Гугл",
"no_notes": "НЕМАЄ НОТАТОК",
"menu": "Меню",
"logout": "ВИЙТИ",
"logout_save": "ВИЙТИ ТА ЗБЕРЕГТИ",
"lang_btn": "МОВА: Українська",
"back": "НАЗАД",
"create_title": "СТВОРЕННЯ НОТАТКИ",
"time_label": "Час:",
"save": "ЗБЕРЕГТИ НОТАТКУ",
"placeholder": "Введіть текст..."
},
"en": {
"title": "NOTES",
"login_btn": "SIGN IN WITH GOOGLE",
"choose_acc": "Choose Google Account",
"no_notes": "NO NOTES",
"menu": "Menu",
"logout": "LOG OUT",
"logout_save": "LOG OUT & SAVE",
"lang_btn": "LANGUAGE: English",
"back": "BACK",
"create_title": "CREATE NOTE",
"time_label": "Time:",
"save": "SAVE NOTE",
"placeholder": "Enter text..."
}
}
self.load_data()
self.build_ui()
if self.account:
self.show_main_screen()
else:
self.show_login_screen()
def load_data(self):
if os.path.exists(DATA_FILE):
try:
with open(DATA_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
self.account = data.get("account")
self.notes = data.get("notes", [])
self.lang = data.get("lang", "uk")
except Exception:
pass
def save_data(self):
data = {
"account": self.account,
"notes": self.notes,
"lang": self.lang
}
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
def t(self, key):
return self.translations[self.lang].get(key, "")
def build_ui(self):
# 1. Екран входу
self.login_frame = tk.Frame(self.root, bg="#121212")
self.lbl_title = tk.Label(self.login_frame, text=self.t("title"), fg="#ff8c00", bg="#121212", font=("Arial", 28, "bold"))
self.lbl_title.pack(pady=(180, 40))
self.btn_google = tk.Button(self.login_frame, text=self.t("login_btn"), bg="#2e7d32", fg="white", font=("Arial", 12, "bold"), bd=0, padx=20, pady=12, command=self.open_google_modal)
self.btn_google.pack()
# 2. Головний екран
self.main_frame = tk.Frame(self.root, bg="#1a1a1a")
self.header = tk.Frame(self.main_frame, bg="#1a1a1a")
self.header.pack(fill="x", padx=15, pady=15)
# Ліва частина шапки: заголовок + пошта
left_header = tk.Frame(self.header, bg="#1a1a1a")
left_header.pack(side="left")
self.lbl_header = tk.Label(left_header, text=self.t("title"), fg="#2e7d32", bg="#1a1a1a", font=("Arial", 16, "bold"))
self.lbl_header.pack(anchor="w")
self.lbl_account_email = tk.Label(left_header, text="", fg="#aaaaaa", bg="#1a1a1a", font=("Arial", 9))
self.lbl_account_email.pack(anchor="w")
self.btn_menu = tk.Button(self.header, text="☰", fg="white", bg="#1a1a1a", font=("Arial", 18), bd=0, command=self.open_menu_modal)
self.btn_menu.pack(side="right")
self.notes_container = tk.Frame(self.main_frame, bg="#1a1a1a")
self.notes_container.pack(fill="both", expand=True, padx=10, pady=10)
# Оранжевий плюсик
self.btn_plus = tk.Button(self.main_frame, text="+", bg="#ff8c00", fg="white", font=("Arial", 24, "bold"), bd=0, command=self.open_create_note_modal)
self.btn_plus.place(relx=0.85, rely=0.9, anchor="center", width=55, height=55)
def show_login_screen(self):
self.main_frame.pack_forget()
self.login_frame.pack(fill="both", expand=True)
def show_main_screen(self):
self.login_frame.pack_forget()
self.main_frame.pack(fill="both", expand=True)
if self.account:
self.lbl_account_email.configure(text=self.account)
self.render_notes()
# Вікно Google-акаунта
def open_google_modal(self):
modal = tk.Toplevel(self.root)
modal.configure(bg="#ffffff")
modal.geometry("300x200")
modal.grab_set()
tk.Label(modal, text=self.t("choose_acc"), bg="#ffffff", fg="#000000", font=("Arial", 12, "bold")).pack(pady=15)
for acc in ["[email protected]", "[email protected]"]:
btn = tk.Button(modal, text=acc, bg="#f1f1f1", fg="#000000", font=("Arial", 10), bd=0, pady=6, command=lambda a=acc: self.select_account(a, modal))
btn.pack(fill="x", padx=20, pady=5)
def select_account(self, acc, modal):
self.account = acc
self.save_data()
modal.destroy()
self.show_main_screen()
# Жовте меню
def open_menu_modal(self):
modal = tk.Toplevel(self.root)
modal.configure(bg="#ffeb3b")
modal.geometry("280x320")
modal.grab_set()
tk.Label(modal, text=self.t("menu"), bg="#ffeb3b", fg="#000000", font=("Arial", 16, "bold")).pack(pady=15)
btn_logout = tk.Button(modal, text=self.t("logout"), bg="#757575", fg="white", font=("Arial", 11), bd=0, pady=8, command=lambda: self.logout(False, modal))
btn_logout.pack(fill="x", padx=25, pady=5)
btn_logout_save = tk.Button(modal, text=self.t("logout_save"), bg="#757575", fg="white", font=("Arial", 11), bd=0, pady=8, command=lambda: self.logout(True, modal))
btn_logout_save.pack(fill="x", padx=25, pady=5)
self.btn_lang = tk.Button(modal, text=self.t("lang_btn"), bg="#757575", fg="white", font=("Arial", 11), bd=0, pady=8, command=self.toggle_language)
self.btn_lang.pack(fill="x", padx=25, pady=5)
btn_back = tk.Button(modal, text=self.t("back"), bg="#9e9e9e", fg="white", font=("Arial", 10, "bold"), bd=0, pady=6, command=modal.destroy)
btn_back.pack(pady=15)
def toggle_language(self):
self.lang = "en" if self.lang == "uk" else "uk"
self.save_data()
self.btn_lang.configure(text=self.t("lang_btn"))
self.lbl_title.configure(text=self.t("title"))
self.btn_google.configure(text=self.t("login_btn"))
self.lbl_header.configure(text=self.t("title"))
self.render_notes()
def logout(self, keep_logged, modal):
modal.destroy()
if not keep_logged:
self.account = None
self.save_data()
self.show_login_screen()
# Зелене вікно створення нотатки
def open_create_note_modal(self):
modal = tk.Toplevel(self.root)
modal.configure(bg="#2e7d32")
modal.geometry("350x560")
modal.grab_set()
tk.Label(modal, text=self.t("create_title"), bg="#2e7d32", fg="white", font=("Arial", 14, "bold")).pack(pady=10)
txt_input = tk.Text(modal, bg="#1a1a1a", fg="white", font=("Arial", 11), bd=0, insertbackground="white")
txt_input.pack(fill="both", expand=True, padx=15, py=5)
lbl_char = tk.Label(modal, text="Поле: (0/300 000 сим)", bg="#2e7d32", fg="#cccccc", font=("Arial", 9))
lbl_char.pack(anchor="e", padx=15)
def on_type(event):
count = len(txt_input.get("1.0", "end-1c"))
lbl_char.configure(text=f"Поле: ({count}/300 000 сим)")
txt_input.bind("<KeyRelease>", on_type)
# Час
time_frame = tk.Frame(modal, bg="#1e4620")
time_frame.pack(fill="x", padx=15, pady=8)
tk.Label(time_frame, text=self.t("time_label"), bg="#1e4620", fg="white", font=("Arial", 11)).pack()
self.current_hour = 0
self.current_minute = 0
selectors_frame = tk.Frame(time_frame, bg="#1e4620")
selectors_frame.pack(pady=5)
btn_hour = tk.Button(selectors_frame, text="00", bg="#121212", fg="white", font=("Arial", 12, "bold"), bd=1, command=lambda: self.inc_hour(btn_hour))
btn_hour.pack(side="left", padx=10)
tk.Label(selectors_frame, text=":", bg="#1e4620", fg="white", font=("Arial", 14, "bold")).pack(side="left")
btn_min = tk.Button(selectors_frame, text="00", bg="#121212", fg="white", font=("Arial", 12, "bold"), bd=1, command=lambda: self.inc_min(btn_min))
btn_min.pack(side="left", padx=10)
# Велика кнопка ЗБЕРЕГТИ НОТАТКУ знизу + Назад
btns_frame = tk.Frame(modal, bg="#2e7d32")
btns_frame.pack(fill="x", padx=15, pady=10)
btn_save = tk.Button(btns_frame, text=self.t("save"), bg="#1b5e20", fg="white", font=("Arial", 11, "bold"), bd=0, pady=8, command=lambda: self.save_note(txt_input.get("1.0", "end-1c"), modal))
btn_save.pack(fill="x", pady=5)
btn_back = tk.Button(btns_frame, text=self.t("back"), bg="#9e9e9e", fg="white", font=("Arial", 10, "bold"), bd=0, pady=6, command=modal.destroy)
btn_back.pack(fill="x")
def inc_hour(self, btn):
self.current_hour = (self.current_hour + 1) % 24
btn.configure(text=f"{self.current_hour:02d}")
def inc_min(self, btn):
self.current_minute = (self.current_minute + 1) % 60
btn.configure(text=f"{self.current_minute:02d}")
def save_note(self, text, modal):
text = text.strip()
if not text:
return
time_str = f"{self.current_hour:02d}:{self.current_minute:02d}"
self.notes.append({"text": text, "time": time_str})
self.save_data()
modal.destroy()
self.render_notes()
def delete_note(self, index):
self.notes.pop(index)
self.save_data()
self.render_notes()
def render_notes(self):
for child in self.notes_container.winfo_children():
child.destroy()
if not self.notes:
lbl_empty = tk.Label(self.notes_container, text=self.t("no_notes"), fg="white", bg="#1a1a1a", font=("Arial", 16, "bold"))
lbl_empty.pack(expand=True)
return
for idx, note in enumerate(self.notes):
card = tk.Frame(self.notes_container, bg="#242424", bd=0)
card.pack(fill="x", py=4, px=5)
# Оранжева смужка зліва
strip = tk.Frame(card, bg="#ff8c00", width=4)
strip.pack(side="left", fill="y")
info = tk.Frame(card, bg="#242424")
info.pack(side="left", fill="x", expand=True, px=8, py=5)
lbl_txt = tk.Label(info, text=note["text"].split("\n")[0][:30], fg="white", bg="#242424", font=("Arial", 11), anchor="w")
lbl_txt.pack(fill="x")
lbl_time = tk.Label(info, text=f"Час: {note['time']}", fg="#aaaaaa", bg="#242424", font=("Arial", 9), anchor="w")
lbl_time.pack(fill="x")
# Червона мусорка
btn_del = tk.Button(card, text="🗑️", bg="#d32f2f", fg="white", font=("Arial", 10), bd=0, command=lambda i=idx: self.delete_note(i))
btn_del.pack(side="right", padx=8, py=5)
if name == "__main__":
root = tk.Tk()
app = NotesApp(root)
root.mainloop()
Готова програма•
Інші продукти в категорії «Інше»
- Психологічна гра DreamWay — Таня Вінар
- СКЕТЧИНГ - ТЕХНІКИ ІНТУЇТИВНОЇ ЛІНІЇ — Pavlo
- Книга — Пружина Олексій
- Подорожуємо без паніки: дитяча аптечка — Tymchshyn
- Життя наперед — Тетяна Дорошенко
- Лев і Мишка — Повна трилогія — Омелян Падовський
- Розмальовки: Гелловінські Муркотики — Михайло Небо
- Лев і Мишка. Том I — Прокляття кохання — Омелян Падовський