【记录】python3 使用tkinter制作tkinterUI编辑器 《二十一》事件管理与多重选择管理

使用tkinter制作tkinterUI编辑器



前言

这篇文章记录一下事件管理与多重选择的实现,这部分代码我没有上传,我打算用新写的事件管理重构一下之前的代码,之后统一上传。
之前的完整代码已上传到github,可从第一篇记录下载


一、需要用到的装饰器

先上代码,decorator.py

def single_instance(cls, *args, **kwargs):

    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return get_instance


def collect_event(event_list, event_type):

    def wrapper(f):
        event_list.append((f, event_type))
        def wrapper2(self, *args, **kwargs):
            return f(self, *args, **kwargs)
        return wrapper2

    return wrapper

说明:

  1. single_instance用于实现单例
  2. collect_event用于收集类中监听事件的函数

二、事件管理

先上代码,eventMgr.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from functools import partial
from decorator import single_instance, collect_event


@single_instance
class eventMgr:

    def __init__(self):
        self.event_dict = {}

    def register_event(self, event_type, event_func):
        self.event_dict.setdefault(event_type, []).append(event_func)

    def dispatch_event(self, event_type, *args, **kwargs):

        if event_type not in self.event_dict:
            return

        for func in self.event_dict[event_type]:
            func(*args, **kwargs)

    def register_event_by_list(self, event_list, funcs_owner):
        for (func, event_type) in event_list:
            self.register_event(event_type, partial(func, funcs_owner))


if __name__ == "__main__":

    class testEvent:

        event_list = []

        def __init__(self):
            self.a = 1
            eventMgr().register_event_by_list(self.event_list, self)

        @collect_event(event_list, "test_1")
        def test_event(self, *args, **kwargs):
            print("test_event_1", self.a, args, kwargs)
            self.a = 2

        @collect_event(event_list, "test_1")
        def test_event_2(self, *args, **kwargs):
            print("test_event_2", self.a, args, kwargs)
            self.a = 3

        @collect_event(event_list, "test_2")
        def test_event_3(self, arg_1, arg_2):
            print("test_event_3", self.a, arg_1, arg_2)
            self.a = 4

    t = testEvent()
    eventMgr().dispatch_event("test_1", "111", e="222")
    eventMgr().dispatch_event("test_1", e="333")
    eventMgr().dispatch_event("test_2", arg_1="444", arg_2="555")
    eventMgr().dispatch_event("test_2", "666", "777")
    t.test_event("888", f=4)
    t.test_event_3("999", "000")

说明:

  1. register_event用于注册事件的回调函数,参数event_type是事件的类型,之前我想定义成枚举,后来觉得太麻烦改成了字符串,参数event_func是回调函数。

  2. 由于类的成员函数想要调用的话需要传self进去,所以添加了一个函数register_event_by_list用于处理类的成员函数。

  3. dispatch_event函数用于派发事件,参数是需要派发的事件类型与需要用的参数。

  4. testEvent展示了如何使用,运行结果如下:

    test_event_1 1 ('111',) {'e': '222'}
    test_event_2 2 ('111',) {'e': '222'}
    test_event_1 3 () {'e': '333'}
    test_event_2 2 () {'e': '333'}
    test_event_3 3 444 555
    test_event_3 4 666 777
    test_event_1 4 ('888',) {'f': 4}
    test_event_3 2 999 000
    

三、多重选择管理

先上代码,selectedMgr.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

from enum import IntEnum
from eventMgr import eventMgr
from decorator import single_instance


class enumSelectedType(IntEnum):
    SELECTED_TYPE_NONE = 0                                  # 未选中
    SELECTED_TYPE_SINGLE = 1                                # 单选
    SELECTED_TYPE_MULTI = 2                                 # 多选


class selectedBase:

    def __init__(self):
        self.no = -1
        self.selected_type = enumSelectedType.SELECTED_TYPE_NONE

    def get_no(self):
        return self.no

    def set_no(self, no):
        if self.no == no:
            return
        self.no = no

    def get_selected_type(self):
        return self.selected_type

    def set_selected_type(self, selected_type):
        if self.selected_type == selected_type:
            return
        self.selected_type = selected_type

    def is_single(self):
        return self.get_selected_type() == enumSelectedType.SELECTED_TYPE_SINGLE

    def is_multi(self):
        return self.get_selected_type() == enumSelectedType.SELECTED_TYPE_MULTI

    def is_selected(self):
        return self.get_selected_type() != enumSelectedType.SELECTED_TYPE_NONE


@single_instance
class selectedMgr:

    def __init__(self):
        self.selected_no = 0
        self.selected_single = -1
        self.selected_dict = {}

    @property
    def cur_single_select(self):
        """
        当前单选选中的
        :return:
        """
        if self.selected_single not in self.selected_dict:
            return None
        return self.selected_dict[self.selected_single]

    def select_by_type(self, s, select_type):
        """
        根据类型选中
        :param s: 要选中的
        :param select_type: 选中类型
        :return: None
        """
        if len(self.selected_dict) <= 0 or select_type == enumSelectedType.SELECTED_TYPE_SINGLE:
            self.select_single(s)
            return

        self.select_multi(s)

    def select_single(self, s):
        """
        单选
        :param s: 要选中或者取消选中的
        :return: None
        """
        if self.cur_single_select is s:
            return

        # 如果之前是多选则切换为单选
        if s.get_no() in self.selected_dict:
            self.change_select(self.cur_single_select, s)
            return

        # 先取消之前所有选中的然后选中这个
        self.cancel_all_select()
        self.add_select(s, enumSelectedType.SELECTED_TYPE_SINGLE)

        eventMgr().dispatch_event("SELECT_MGR_SELECT_SINGLE_SUCCESS", s)

    def add_select(self, s, selected_type):
        """
        添加一个选中
        :param s: 被选中的
        :param selected_type: 选中类型
        :return: None
        """
        s.set_selected_type(selected_type)
        s.set_no(self.selected_no)

        self.selected_dict[self.selected_no] = s
        if selected_type == enumSelectedType.SELECTED_TYPE_SINGLE:
            self.selected_single = self.selected_no

        self.selected_no += 1

    def cancel_all_select(self):
        """
        取消所有选中
        :return: None
        """
        for s in self.selected_dict.values():
            s.set_selected_type(enumSelectedType.SELECTED_TYPE_NONE)

        eventMgr().dispatch_event("SELECT_MGR_CANCEL_ALL_SELECT_SUCCESS", self.selected_dict.values())

        self.selected_single = -1
        self.selected_dict.clear()

    def change_select(self, single, multi):
        """
        单选切换成多选,多选切换成单选
        :param single: 单选的
        :param multi: 多选的
        :return: None
        """
        single.set_selected_type(enumSelectedType.SELECTED_TYPE_MULTI)
        multi.set_selected_type(enumSelectedType.SELECTED_TYPE_SINGLE)

        self.selected_single = multi.get_no()
        eventMgr().dispatch_event("SELECT_MGR_SELECT_CHANGE", single, multi)

    def select_multi(self, s):
        """
        多选
        :param s: 要选中或者取消选中的
        :return: None
        """
        if s.get_no() in self.selected_dict:
            self.cancel_select(s)
            return

        self.add_select(s, enumSelectedType.SELECTED_TYPE_MULTI)
        eventMgr().dispatch_event("SELECT_MGR_SELECT_MULTI_SUCCESS", s)

    def select_first(self):
        """
        选中第一个
        :return: None
        """
        if len(self.selected_dict) <= 0:
            return

        keys = sorted(self.selected_dict.keys())
        self.selected_dict[keys[0]].set_selected_type(enumSelectedType.SELECTED_TYPE_SINGLE)
        self.selected_single = self.selected_dict[keys[0]].get_no()

        eventMgr().dispatch_event("SELECT_MGR_SELECT_SINGLE_SUCCESS", self.selected_dict[keys[0]])

    def cancel_select(self, s):
        """
        取消选中
        :param s: 被取消的
        :return: None
        """
        if s is None or s.get_no() not in self.selected_dict:
            return

        old_select_type = s.get_selected_type()
        s.set_selected_type(enumSelectedType.SELECTED_TYPE_NONE)

        self.selected_dict.pop(s.get_no())
        eventMgr().dispatch_event("SELECT_MGR_CANCEL_SELECT_SUCCESS", s, old_select_type)

        # 取消单选
        if old_select_type == enumSelectedType.SELECTED_TYPE_SINGLE:
            self.selected_single = -1
            self.select_first()

说明:

  1. selectedBase类是被选择的基类。
  2. 调用管理器的select_by_type函数进行单选或者多选,选择成功后使用事件管理器派发事件,参数s就是 selectedBase类的实例或者是继承selectedBase类的实例,select_type就是enumSelectedType中的枚举。

上一篇记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

archmage199

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值