/
sosh6yug
/
Gen_Task
Обзор
Документация
Войти
/
sosh6yug
/
Gen_Task
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
1.py
242 строки
11 KB
sosh6yug
create: .gitignore, 1.py, README.md, task_history.json
05 май 2026, 14:28
Верифицирован
05 май 2026, 14:28
bfb35dc
Код
Авторство
О чём код?
import tkinter as tk from tkinter import ttk, messagebox import random import json import os from datetime import datetime # --- Предопределённые задачи --- DEFAULT_TASKS = [ {"name": "Прочитать статью по Python", "type": "учёба"}, {"name": "Сделать 10 минут зарядки", "type": "спорт"}, {"name": "Ответить на рабочие письма", "type": "работа"}, {"name": "Изучить новую библиотеку", "type": "учёба"}, {"name": "Пройти 5000 шагов", "type": "спорт"}, {"name": "Завершить отчёт", "type": "работа"}, {"name": "Посмотреть вебинар", "type": "учёба"}, {"name": "Сделать растяжку", "type": "спорт"}, {"name": "Провести совещание", "type": "работа"} ] HISTORY_FILE = "task_history.json" class TaskGenerator: def __init__(self, root): self.root = root self.root.title("Random Task Generator") self.root.geometry("700x600") self.root.resizable(True, True) # Данные self.tasks = DEFAULT_TASKS.copy() self.history = [] # каждый элемент: {"name": ..., "type": ..., "timestamp": ...} self.load_history() # Переменные фильтров self.filter_type_var = tk.StringVar() # --- Интерфейс --- # Верхняя панель с кнопкой генерации top_frame = ttk.Frame(root, padding="10") top_frame.pack(fill=tk.X) self.generate_btn = ttk.Button(top_frame, text="🎲 Сгенерировать задачу", command=self.generate_task) self.generate_btn.pack(pady=5) # Панель фильтров filter_frame = ttk.LabelFrame(root, text="Фильтрация истории", padding="5") filter_frame.pack(fill=tk.X, padx=10, pady=5) ttk.Label(filter_frame, text="Тип задачи:").grid(row=0, column=0, padx=5) self.type_combo = ttk.Combobox(filter_frame, textvariable=self.filter_type_var, state="readonly", width=15) self.type_combo['values'] = ["Все", "учёба", "спорт", "работа"] self.type_combo.set("Все") self.type_combo.grid(row=0, column=1, padx=5) self.type_combo.bind("<<ComboboxSelected>>", lambda e: self.update_history_display()) ttk.Button(filter_frame, text="Сбросить фильтры", command=self.reset_filters).grid(row=0, column=2, padx=10) ttk.Button(filter_frame, text="➕ Добавить задачу", command=self.add_task_dialog).grid(row=0, column=3, padx=10) # Список истории history_frame = ttk.LabelFrame(root, text="История задач", padding="5") history_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5) # Создаём фрейм для списка с прокруткой list_frame = ttk.Frame(history_frame) list_frame.pack(fill=tk.BOTH, expand=True) self.history_listbox = tk.Listbox(list_frame, height=15, font=("Arial", 10)) scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.history_listbox.yview) self.history_listbox.configure(yscrollcommand=scrollbar.set) self.history_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # Отображение текущей задачи self.current_task_label = ttk.Label(root, text="Нажмите кнопку, чтобы получить задачу", wraplength=650, justify="center", font=("Arial", 11, "bold")) self.current_task_label.pack(pady=10, padx=10, fill=tk.X) # Статус-бар self.status_var = tk.StringVar() self.status_var.set("Готов к работе") status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W) status_bar.pack(side=tk.BOTTOM, fill=tk.X) # Отобразить начальную историю self.update_history_display() # Обработка закрытия self.root.protocol("WM_DELETE_WINDOW", self.on_close) def load_history(self): """Загружает историю из JSON файла""" if os.path.exists(HISTORY_FILE): try: with open(HISTORY_FILE, "r", encoding="utf-8") as f: self.history = json.load(f) self.status_var.set(f"Загружено {len(self.history)} задач из истории") except (json.JSONDecodeError, IOError) as e: print(f"Ошибка загрузки: {e}") self.history = [] else: self.history = [] def save_history(self): """Сохраняет историю в JSON файл""" try: with open(HISTORY_FILE, "w", encoding="utf-8") as f: json.dump(self.history, f, ensure_ascii=False, indent=2) return True except Exception as e: messagebox.showerror("Ошибка", f"Не удалось сохранить историю: {e}") return False def generate_task(self): """Выбирает случайную задачу и добавляет в историю""" if not self.tasks: messagebox.showwarning("Нет задач", "Добавьте хотя бы одну задачу перед генерацией.") return task = random.choice(self.tasks) task_copy = { "name": task["name"], "type": task["type"], "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } self.history.append(task_copy) self.save_history() # Показать текущую задачу type_emoji = {"учёба": "📚", "спорт": "🏃", "работа": "💼"} emoji = type_emoji.get(task["type"], "✅") self.current_task_label.config( text=f"{emoji} {task['name']}\n(Тип: {task['type']})", foreground="green" ) self.status_var.set(f"Сгенерирована задача: {task['name']}") self.update_history_display() # Анимация мигания кнопки (опционально) self.generate_btn.config(text="✅ Сгенерировано!") self.root.after(1000, lambda: self.generate_btn.config(text="🎲 Сгенерировать задачу")) def reset_filters(self): """Сбрасывает фильтры""" self.filter_type_var.set("Все") self.update_history_display() self.status_var.set("Фильтры сброшены") def update_history_display(self): """Обновляет отображение списка истории с учётом фильтров""" self.history_listbox.delete(0, tk.END) filtered = self.history type_filter = self.filter_type_var.get() if type_filter != "Все": filtered = [task for task in filtered if task["type"] == type_filter] if not filtered: self.history_listbox.insert(tk.END, "📭 Нет задач по выбранному фильтру") return for task in filtered: # Форматируем вывод: [дата] тип → название type_emoji = {"учёба": "📚", "спорт": "🏃", "работа": "💼"} emoji = type_emoji.get(task["type"], "•") display = f"[{task['timestamp']}] {emoji} {task['type'].upper()} → {task['name']}" self.history_listbox.insert(tk.END, display) def add_task_dialog(self): """Диалог для добавления новой задачи""" dialog = tk.Toplevel(self.root) dialog.title("Добавить задачу") dialog.geometry("450x250") dialog.transient(self.root) dialog.grab_set() # Центрируем диалог dialog.update_idletasks() x = self.root.winfo_x() + (self.root.winfo_width() - 450) // 2 y = self.root.winfo_y() + (self.root.winfo_height() - 250) // 2 dialog.geometry(f"+{x}+{y}") # Поля ввода ttk.Label(dialog, text="Название задачи:", font=("Arial", 10, "bold")).pack(pady=(15, 5)) name_entry = ttk.Entry(dialog, width=50) name_entry.pack(pady=5, padx=20, fill=tk.X) ttk.Label(dialog, text="Тип задачи:", font=("Arial", 10, "bold")).pack(pady=(10, 5)) type_var = tk.StringVar() type_combo = ttk.Combobox(dialog, textvariable=type_var, values=["учёба", "спорт", "работа"], state="readonly", width=20) type_combo.pack(pady=5) type_combo.set("учёба") def save_task(): name = name_entry.get().strip() task_type = type_var.get() # Проверка на пустую строку if not name: messagebox.showerror("Ошибка", "Название задачи не может быть пустым!", parent=dialog) return # Проверка на существование такой же задачи for task in self.tasks: if task["name"].lower() == name.lower() and task["type"] == task_type: messagebox.showwarning("Предупреждение", "Такая задача уже существует!", parent=dialog) return new_task = {"name": name, "type": task_type} self.tasks.append(new_task) messagebox.showinfo("Успех", f"Задача «{name}» добавлена!", parent=dialog) self.status_var.set(f"Добавлена новая задача: {name}") dialog.destroy() button_frame = ttk.Frame(dialog) button_frame.pack(pady=20) ttk.Button(button_frame, text="Сохранить", command=save_task, width=15).pack(side=tk.LEFT, padx=5) ttk.Button(button_frame, text="Отмена", command=dialog.destroy, width=15).pack(side=tk.LEFT, padx=5) name_entry.focus() def on_close(self): """При закрытии окна сохраняем историю""" if self.save_history(): self.status_var.set("История сохранена") self.root.destroy() if __name__ == "__main__": root = tk.Tk() # Установка иконки (если есть файл, иначе пропускаем) try: root.iconbitmap(default='icon.ico') except: pass app = TaskGenerator(root) root.mainloop()