# 31. Event-Driven Programming

Here are 10 Python code snippets to demonstrate event-driven programming concepts using callbacks, signals, and event-handling patterns:

***

**1. Basic Event-Driven Callback**

```python
def event_handler(event_name):
    print(f"Event triggered: {event_name}")

def trigger_event(callback, event_name):
    callback(event_name)

trigger_event(event_handler, "Button Clicked")
```

***

**2. Event Dispatcher with Multiple Callbacks**

```python
class EventDispatcher:
    def __init__(self):
        self.events = {}

    def register(self, event_name, callback):
        if event_name not in self.events:
            self.events[event_name] = []
        self.events[event_name].append(callback)

    def dispatch(self, event_name, *args, **kwargs):
        if event_name in self.events:
            for callback in self.events[event_name]:
                callback(*args, **kwargs)

def on_click(event_name):
    print(f"{event_name} event handled!")

dispatcher = EventDispatcher()
dispatcher.register("click", on_click)
dispatcher.dispatch("click", "Button Clicked")
```

***

**3. Using `signal` Module for Event Handling**

```python
import signal
import time

def handle_signal(signum, frame):
    print(f"Signal {signum} received!")

signal.signal(signal.SIGINT, handle_signal)

print("Press Ctrl+C to send SIGINT...")
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("Exiting program.")
```

***

**4. Event Listener with Custom Class**

```python
class Event:
    def __init__(self):
        self.listeners = []

    def connect(self, callback):
        self.listeners.append(callback)

    def emit(self, *args, **kwargs):
        for listener in self.listeners:
            listener(*args, **kwargs)

def on_data_received(data):
    print(f"Data received: {data}")

event = Event()
event.connect(on_data_received)
event.emit("Hello, Event-Driven Programming!")
```

***

**5. Tkinter GUI Example with Event Binding**

```python
import tkinter as tk

def on_button_click():
    print("Button clicked!")

root = tk.Tk()
button = tk.Button(root, text="Click Me", command=on_button_click)
button.pack()

root.mainloop()
```

***

**6. Asynchronous Event Loop with Callbacks**

```python
import asyncio

async def event_producer(callback):
    for i in range(5):
        await asyncio.sleep(1)
        callback(f"Event {i}")

def event_handler(event):
    print(f"Handled: {event}")

asyncio.run(event_producer(event_handler))
```

***

**7. Custom Signal with `blinker` Library**

```python
from blinker import signal

my_signal = signal("custom_event")

def on_custom_event(sender, **kwargs):
    print(f"Received signal from {sender} with data: {kwargs}")

my_signal.connect(on_custom_event)
my_signal.send("Sender", data="Hello, Signals!")
```

*Install `blinker` with `pip install blinker`.*

***

**8. PyQt Signal and Slot Example**

```python
from PyQt5.QtCore import QObject, pyqtSignal

class MyObject(QObject):
    my_signal = pyqtSignal(str)

    def trigger_signal(self):
        self.my_signal.emit("Hello, PyQt!")

def on_signal_received(message):
    print(f"Signal received: {message}")

obj = MyObject()
obj.my_signal.connect(on_signal_received)
obj.trigger_signal()
```

*Install PyQt5 with `pip install pyqt5`.*

***

**9. Observable Pattern with Callbacks**

```python
class Observable:
    def __init__(self):
        self.observers = []

    def register(self, observer):
        self.observers.append(observer)

    def notify(self, data):
        for observer in self.observers:
            observer(data)

def observer_one(data):
    print(f"Observer 1: {data}")

def observer_two(data):
    print(f"Observer 2: {data}")

observable = Observable()
observable.register(observer_one)
observable.register(observer_two)
observable.notify("Event Triggered")
```

***

**10. File System Watcher with `watchdog`**

```python
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class MyHandler(FileSystemEventHandler):
    def on_modified(self, event):
        print(f"File modified: {event.src_path}")

if __name__ == "__main__":
    path = "."
    event_handler = MyHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=False)
    observer.start()

    try:
        while True:
            pass
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
```

*Install `watchdog` with `pip install watchdog`.*

***

These examples cover various event-driven programming techniques, including custom event handling, GUI interaction, signals, callbacks, and asynchronous event loops.
