در برنامهٔ خطی، تو جریان را کنترل میکنی؛ در برنامهٔ گرافیکی، کاربر کنترل میکند. برنامهات میخوابد، رویداد میآید (کلیک، کلید، تایمر)، تابعی صدا زده میشود و دوباره میخوابد. اسم این خوابوبیداری حلقهٔ رویداد (event loop) است.
حلقهٔ رویداد به زبان ساده
# شبیهسازی ذهنی حلقهٔ رویداد (بدون هیچ کتابخانهای)
events = ["click:save", "key:a", "click:quit"]
handlers = {
"click:save": lambda: print("ذخیره شد."),
"key:a": lambda: print("حرف a تایپ شد."),
}
for event in events: # این همان کاری است که حلقهٔ رویداد برایت میکند
if event == "click:quit":
break
handlers.get(event, lambda: print("رویداد ناشناخته:", event))()
نکتهٔ طلایی: callback باید سریع باشد. اگر callback ده ثانیه حساب کتاب کند، کل رابط قفل میشود چون حلقهٔ رویداد منتظر برگشتن اوست. کار سنگین → ریسه جدا یا حالت «مشغولم».
قانون مقدس: جدایی منطق از نما
منطق برنامه (مثلاً جمع سبد) باید تابعی خالص و تستپذیر باشد که هیچچیز از دکمه و پنجره نمیداند. کد GUI فقط آن را صدا میزند و نتیجه را نشان میدهد.
# logic.py — خالص، بدون هیچ وابستگی به GUI، کاملاً تستپذیر
def add_item(cart, name, price):
cart.append({"name": name, "price": price})
return cart
def cart_total(cart):
return sum(item["price"] for item in cart)
# gui_app.py — فقط نما (اجرا در محیط گرافیکی با tkinter)
import tkinter as tk
from logic import add_item, cart_total
cart = []
root = tk.Tk()
root.title("سبد خرید")
label = tk.Label(root, text="جمع: ۰")
label.pack()
def on_add():
add_item(cart, "کتاب", 12000)
label.config(text=f"جمع: {cart_total(cart)}")
tk.Button(root, text="افزودن کتاب", command=on_add).pack()
root.mainloop() # شروع حلقهٔ رویداد — این خط تا بستهشدن پنجره برنمیگردد
اشتباه رایج
برای برنامهٔ گرافیکی باید کل منطق را داخل callback دکمهها نوشت.
تصحیح
callback فقط مترجم است: ورودی ویجت را میگیرد، تابع منطق را صدا میزند، نتیجه را نمایش میدهد. منطق همان کدی است که در کنسول هم کار میکند.
سنجش فهم — رویدادمحوری
۰ از ۲ پاسخ داده شده