使用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
说明:
- single_instance用于实现单例
- 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")
说明:
-
register_event用于注册事件的回调函数,参数event_type是事件的类型,之前我想定义成枚举,后来觉得太麻烦改成了字符串,参数event_func是回调函数。
-
由于类的成员函数想要调用的话需要传self进去,所以添加了一个函数register_event_by_list用于处理类的成员函数。
-
dispatch_event函数用于派发事件,参数是需要派发的事件类型与需要用的参数。
-
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()
说明:
- selectedBase类是被选择的基类。
- 调用管理器的select_by_type函数进行单选或者多选,选择成功后使用事件管理器派发事件,参数s就是 selectedBase类的实例或者是继承selectedBase类的实例,select_type就是enumSelectedType中的枚举。