μλ νλ‘κ·Έλ¨ - GPTxPython
μ€λͺ
νλ‘κ·Έλ¨
ν둬ννΈ
νλ₯΄μλ
- νμ΄μ¬ νλ‘κ·Έλλ° νμ΅μ
μμ
- μλ νλ‘κ·Έλ¨ κ°λ°
λ§₯λ½
- μΈμ΄ : νμ΄μ¬
- λ²μ : 3.13
- ꡬ쑰 : GUI νλ‘κ·Έλ¨
- κΈ°λ₯
* λ€μ€ μλ κ΄λ¦¬ νλ‘κ·Έλ¨
* μ μ₯λ μλ λͺ©λ‘ νμΈ
* MySQL λ°μ΄ν°λ² μ΄μ€λ‘ μλ μ 보 κ΄λ¦¬
* μλ μ 보 κ΄λ¦¬ : μλ μ΄λ¦ λ³κ²½, μλ μ리 λ³κ²½, μλ λ μ§ μκ° λ³κ²½
* μλ κ΄λ¦¬ λμ보λ
: λ±λ‘λ μλ 리μ€νΈλ‘ νμΈ, μμ μμ μμ΄μ½ λ²νΌμΌλ‘ κ΄λ¦¬
* μλ 리μ€νΈμ μΉ΄λ ν΄λ¦ μ μμ νλ©΄μΌλ‘ μ΄λ
* μλ μμ νλ©΄ : μ΄λ¦, μ리, λ μ§μκ° λ³κ²½
* DB μ μ μ alarm ν
μ΄λΈ μμ±
* κΈ°λ³Έ μλ μ리λ c:/alarm/ ν΄λμμ μ ν
* μ΅μ΄ μλ μ리λ c:/alaram/κΈ°λ³Έ.mp3
νμ
- μλ μκ° λλ¬ μ, μλμ° notification μλ¦ΌμΌλ‘ μλ μ΄λ¦κ³Ό μκ° μΆλ ₯
- μ§μ ν μλ μ리λ₯Ό μλλκΈ° λ²νΌ ν΄λ¦ μ κΉμ§ λ°λ³΅ μ¬μ
μλ mp3 νμΌμ μ¬μμκ°μ νμΈνμ¬ ν λ²μ μ¬μμ΄ λλ λ€ λ€μ μ¬μ λ°λ³΅
μμ
- μλ λ±λ‘ λ²νΌ ν΄λ¦ μ, μλ μ΄λ¦κ³Ό μλ λ μ§ μκ° μ ννκ³
μλ λ μ§μκ°μ ν
μ€νΈ μ
λ ₯λ§κ³ λ¬λ ₯ μκ³ μ
λ ₯μΌλ‘
μλ μ리λ₯Ό μ νμμμμ μ ν, κΈ°λ³Έμ c:/alaram/κΈ°λ³Έ.mp3
μ΄λ κ² λ±λ‘ν μλμ λμ보λμ μΆλ ₯λκ³ , μμ μμ λ²νΌμΌλ‘ κ΄λ¦¬
λμ보λμμ ν΄λΉ μλ λλΈν΄λ¦ μ, νλ‘κ·Έλ μ€λ°μ λΌλ²¨λ‘ λ¨μ μκ° νμνλ νλ©΄μΌλ‘ μ΄λ
μΊλ²μ€ λͺ¨λλ‘ μλ΅
Plain Text
볡μ¬
μ½λ
import os
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from tkcalendar import Calendar, DateEntry
from datetime import datetime, timedelta
import threading
import time
import pygame
import mysql.connector
from plyer import notification
# ===================== DB SETUP =====================
def connect_db():
# MySQL DBμ μ°κ²°νκ³ alarm ν
μ΄λΈ μμ± (status μΆκ°)
conn = mysql.connector.connect(
host='localhost', user='python', password='123456', database='python'
)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS alarm (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
time DATETIME,
sound_path TEXT,
status VARCHAR(10) DEFAULT 'on' -- μλ μν (on/off)
)
''')
conn.commit()
return conn
# ===================== ALARM PLAYER =====================
def play_alarm(sound_path):
# μλ μ리λ₯Ό λ°λ³΅ μ¬μ (stop_eventκ° μ€μ λ λκΉμ§)
pygame.mixer.init()
pygame.mixer.music.load(sound_path)
while not stop_event.is_set():
pygame.mixer.music.play()
time.sleep(pygame.mixer.Sound(sound_path).get_length())
def notify_user(title, msg):
# μλμ° μλ¦Όμ λμ
notification.notify(
title=title,
message=msg,
timeout=5
)
# ===================== MAIN APP =====================
class AlarmApp:
def __init__(self, root):
self.root = root
self.root.title("μλ λμ보λ")
self.conn = connect_db()
self.cursor = self.conn.cursor()
self.frame = ttk.Frame(root, padding=10)
self.frame.pack(fill='both', expand=True)
self.add_button = ttk.Button(self.frame, text="μλ λ±λ‘", command=self.open_add_alarm_window)
self.add_button.pack(pady=5)
# μλ 리μ€νΈ μΆλ ₯μ© TreeView ꡬμ±
self.tree = ttk.Treeview(self.frame, columns=('Name', 'Time', 'Sound', 'Status'), show='headings')
self.tree.heading('Name', text='μλ μ΄λ¦')
self.tree.heading('Time', text='μλ μκ°')
self.tree.heading('Sound', text='μλ μ리')
self.tree.heading('Status', text='μν')
self.tree.pack(fill='both', expand=True)
self.tree.bind('<Double-1>', self.open_edit_alarm_window)
self.load_alarms()
self.check_alarms()
def load_alarms(self):
# DBμμ μλ λͺ©λ‘μ λΆλ¬μ TreeViewμ νμ
for row in self.tree.get_children():
self.tree.delete(row)
self.cursor.execute("SELECT id, name, time, sound_path, status FROM alarm")
for id, name, time_, sound, status in self.cursor.fetchall():
self.tree.insert('', 'end', iid=id, values=(name, time_, os.path.basename(sound), status))
def open_add_alarm_window(self):
AlarmEditor(self.root, self.conn, self.load_alarms)
def open_edit_alarm_window(self, event):
selected = self.tree.focus()
if selected:
alarm_id = int(selected)
AlarmEditor(self.root, self.conn, self.load_alarms, alarm_id)
def check_alarms(self):
# μ£ΌκΈ°μ μΌλ‘ νμ¬ μκ°κ³Ό μλ μκ° λΉκ΅νμ¬ μ€ν 쑰건 체ν¬
def run():
while True:
self.cursor.execute("SELECT id, name, time, sound_path FROM alarm WHERE status='on'")
for alarm_id, name, alarm_time, sound in self.cursor.fetchall():
now = datetime.now()
# μλ μκ°μ΄ μ§λ¬κ³ μμ§ μΈλ¦¬μ§ μμ μλμ΄λ©΄ μ€ν
if now >= alarm_time and not active_alarms.get(alarm_id):
active_alarms[alarm_id] = True
threading.Thread(target=self.trigger_alarm, args=(alarm_id, name, alarm_time, sound)).start()
time.sleep(10)
threading.Thread(target=run, daemon=True).start()
def trigger_alarm(self, alarm_id, name, alarm_time, sound):
# μλ μ€ν: μλ¦Ό νμ λ° μ리 μ¬μ
notify_user("μλ", f"{name} - {alarm_time.strftime('%Y-%m-%d %H:%M:%S')}")
global stop_event
stop_event = threading.Event()
threading.Thread(target=play_alarm, args=(sound,), daemon=True).start()
# μλ μ’
λ£μ© νμ
μλμ°
stop_window = tk.Toplevel(self.root)
stop_window.title("μλ μΈλ¦Ό")
ttk.Label(stop_window, text=f"μλ: {name}").pack(pady=10)
ttk.Label(stop_window, text=f"μκ°: {alarm_time}").pack(pady=5)
stop_btn = ttk.Button(stop_window, text="μλ λκΈ°", command=lambda: self.stop_alarm(stop_window, alarm_id))
stop_btn.pack(pady=20)
def stop_alarm(self, window, alarm_id):
# μλ μ μ§ μ²λ¦¬: μ리 μ€μ§ + DB μν λ³κ²½
stop_event.set()
pygame.mixer.music.stop()
window.destroy()
# μλ μνλ₯Ό 'off'λ‘ μ
λ°μ΄νΈ
self.cursor.execute("UPDATE alarm SET status='off' WHERE id=%s", (alarm_id,))
self.conn.commit()
self.load_alarms()
# ===================== ALARM EDITOR =====================
class AlarmEditor:
def __init__(self, root, conn, refresh_callback, alarm_id=None):
self.conn = conn
self.cursor = conn.cursor()
self.refresh_callback = refresh_callback
self.alarm_id = alarm_id
self.top = tk.Toplevel(root)
self.top.title("μλ μμ " if alarm_id else "μλ λ±λ‘")
# μλ μ΄λ¦ μ
λ ₯
ttk.Label(self.top, text="μλ μ΄λ¦").grid(row=0, column=0, padx=5, pady=5)
self.name_entry = ttk.Entry(self.top)
self.name_entry.grid(row=0, column=1, padx=5, pady=5)
# λ μ§ μ ν
ttk.Label(self.top, text="μλ λ μ§").grid(row=1, column=0, padx=5, pady=5)
self.date_entry = DateEntry(self.top, width=12, background='darkblue', foreground='white', borderwidth=2)
self.date_entry.grid(row=1, column=1, padx=5, pady=5)
# μκ° μ
λ ₯ (μ:λΆ)
ttk.Label(self.top, text="μκ° (HH:MM)").grid(row=2, column=0, padx=5, pady=5)
self.time_entry = ttk.Entry(self.top)
self.time_entry.insert(0, "08:00") # κΈ°λ³Έκ° μ€μ
self.time_entry.grid(row=2, column=1, padx=5, pady=5)
# μλ μ리 μ ν
ttk.Label(self.top, text="μλ μ리").grid(row=3, column=0, padx=5, pady=5)
self.sound_combo = ttk.Combobox(self.top, values=self.load_sounds())
self.sound_combo.set("κΈ°λ³Έ.mp3")
self.sound_combo.grid(row=3, column=1, padx=5, pady=5)
# μ μ₯ λ²νΌ
save_btn = ttk.Button(self.top, text="μ μ₯", command=self.save_alarm)
save_btn.grid(row=4, column=0, pady=10)
# μμ μ μμ λ²νΌλ νμ
if alarm_id:
delete_btn = ttk.Button(self.top, text="μμ ", command=self.delete_alarm)
delete_btn.grid(row=4, column=1, pady=10)
if alarm_id:
self.load_alarm_data()
def load_sounds(self):
# μλ μ¬μ΄λ ν΄λμμ mp3 νμΌ λͺ©λ‘ κ°μ Έμ€κΈ°
sound_dir = "c:/alarm"
return [f for f in os.listdir(sound_dir) if f.endswith(".mp3")]
def load_alarm_data(self):
# DBμμ μλ μ 보 λ‘λνμ¬ νΌμ μ€μ
self.cursor.execute("SELECT name, time, sound_path FROM alarm WHERE id=%s", (self.alarm_id,))
name, time_, sound = self.cursor.fetchone()
self.name_entry.insert(0, name)
self.date_entry.set_date(time_)
self.time_entry.delete(0, tk.END)
self.time_entry.insert(0, time_.strftime("%H:%M"))
self.sound_combo.set(os.path.basename(sound))
def save_alarm(self):
# νΌμμ μ
λ ₯ν λ°μ΄ν°λ₯Ό μ μ₯νκ±°λ μ
λ°μ΄νΈ
name = self.name_entry.get()
date_str = self.date_entry.get_date().strftime("%Y-%m-%d")
time_str = self.time_entry.get()
datetime_str = f"{date_str} {time_str}:00"
sound = os.path.join("c:/alarm", self.sound_combo.get())
if self.alarm_id:
self.cursor.execute(
"UPDATE alarm SET name=%s, time=%s, sound_path=%s, status='on' WHERE id=%s",
(name, datetime_str, sound, self.alarm_id)
)
else:
self.cursor.execute(
"INSERT INTO alarm (name, time, sound_path, status) VALUES (%s, %s, %s, 'on')",
(name, datetime_str, sound)
)
self.conn.commit()
self.refresh_callback()
self.top.destroy()
def delete_alarm(self):
# μλ μμ νμΈ ν DBμμ μ κ±°
if messagebox.askyesno("μμ νμΈ", "μ΄ μλμ μμ νμκ² μ΅λκΉ?"):
self.cursor.execute("DELETE FROM alarm WHERE id=%s", (self.alarm_id,))
self.conn.commit()
self.refresh_callback()
self.top.destroy()
# ===================== MAIN =====================
if __name__ == "__main__":
active_alarms = {} # νμ¬ μ€ν μ€μΈ μλ λͺ©λ‘
stop_event = threading.Event() # μλ μ€μ§ μ΄λ²€νΈ
root = tk.Tk()
app = AlarmApp(root)
root.mainloop()
Python
볡μ¬