如何在Python中实现事件?

Luc*_*uke 4 events tkinter python-3.x

无法弄清楚如何实现事件系统。我正在用 tkinter 做项目。我需要使用事件。如何拥有像 Java 或 C# 事件这样的事件?

我搜索了很多但找不到正确的方法。

这是我试图实现的事件类。

class Event(object):

    def __init__(self):
        self.handlers = []

    def add(self, handler):
        self.handlers.append(handler)
        return self

    def remove(self, handler):
        self.handlers.remove(handler)
        return self

    def fire(self, sender, earg=None):
        for handler in self.handlers:
            value = handler()
            self.remove(handler)
            return value


    __iadd__ = add
    __isub__ = remove
    __call__ = fire
Run Code Online (Sandbox Code Playgroud)

这是汽车类

class Car:
    _speed = 0
    events = Event()

    def speed_up(self):
        self._speed += 10

    def speed_down(self):
        self._speed -= 10

    def get_speed(self):
        return self._speed
Run Code Online (Sandbox Code Playgroud)

最后是 Window 类(tkinter 窗口)

class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.car = Car()
        tk.Button(self, text="Speed Up", command=self.increase_speed).grid(sticky="nsew")
        tk.Button(self, text="Speed Down", command=self.decrease_speed).grid(sticky="nsew")
        self.speed_label = tk.Label(self, text="0")
        self.speed_label.grid(sticky="nsew")
        self.mainloop()

    def increase_speed(self):
        self.car

    def decrease_speed(self):
        pass
Run Code Online (Sandbox Code Playgroud)

这是 tkinter 窗口: tkinter 窗口

我想完成: 1)在“加速”按钮上单击“speed_up”应添加到事件中。2)它应该改变self.speed_label的值。3) 它应该是类似 c# / Java events 或 c# delagetes 的东西。

试图向我学习这个新概念。但实施起来很困难......

更新!我正在搜索/编辑并提出了一个解决方案。不知道这个解决方案好不好。我会问我的老师这是否是实施活动的好方法。但目前代码如下所示:

import tkinter as tk

class Observer():
    _observers = []
    def __init__(self):
        self._observers.append(self)
        self._observed_events = []
    def observe(self, event_name, callback_fn):
        self._observed_events.append({'event_name' : event_name, 'callback_fn' : callback_fn})


class Event():
    def send(self, event_name, *callback_args):
        for observer in Observer._observers:
            for observable in observer._observed_events:
                if observable['event_name'] == event_name:
                    observable['callback_fn'](*callback_args)

    def receive(self, event_name, *callback_args):
        for observer in Observer._observers:
            for observable in observer._observed_events:
                if observable['event_name'] == event_name:
                    response = observable['callback_fn'](*callback_args)
                    return response

class Car(Observer):
    def __init__(self):
        Observer.__init__(self)
        self._current_speed = 0

    def speed(self):
        self._current_speed += 10

    def slow(self):
        self._current_speed -= 10

    def current(self):
        return self._current_speed


class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self._car = Car()
        self.store()
        self.events = Event()
        tk.Button(self, text="Speed Up", command=lambda:self.change_speed("speed")).grid(sticky="nsew")
        tk.Button(self, text="Slow Down", command=lambda:self.change_speed("slow")).grid(sticky="nsew")
        self.label = tk.Label(self, text=0)
        self.label.grid()
        self.settings()


    def store(self):
        self._car.observe("speed", self._car.speed)
        self._car.observe("slow", self._car.slow)
        self._car.observe("current", self._car.current)

    def settings(self):
        self.mainloop()

    def change_speed(self, event):
        self.events.send(event)
        self.label.config(text=self.events.receive("current"))



Window()
Run Code Online (Sandbox Code Playgroud)

Nag*_*gev 7

在没有完全分析问题中的代码的情况下,我想说您使用函数回调的方向​​是正确的。据我所知,这是因为 Python 没有事件的本机实现。

一些有用的库或在此基础上构建的示例可以在观察者模式、模仿事件或相关问题的答案等文章中看到。

这是我能想到的最简单的代码,它说明了回调概念,不带参数:

   def on_notify():
       print("OK, I'm up-to-date")

   def do_something(update):
       # do whatever I need to do
       print("I've changed\n")
       update()

   do_something(on_notify)
Run Code Online (Sandbox Code Playgroud)

哪个输出:

我已经改变了

好的,我已经更新了

当事件发生时,我们的“worker”函数需要一个函数参数来调用。在本例中,它只有一个,但可以使用一个列表,这样我们就有很多观察者,这就是其他更完整的示例所做的。

同样相关的是事件对象,它是对象在线程之间通信的机制,对于用户界面来说这是值得考虑的。我的猜测是,大多数实现“丢失事件”功能的库和框架都基于这些核心方法中的一个或两个。