-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfastcanvas.py
109 lines (88 loc) · 3.23 KB
/
fastcanvas.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import tkinter as tk
from dataclasses import dataclass
from typing import Optional
@dataclass
class Rectangle:
args: tuple
kwargs: dict
tk_id: Optional[int] = None
@dataclass
class Line:
args: tuple
kwargs: dict
tk_id: Optional[int] = None
@dataclass
class Text:
args: tuple
kwargs: dict
tk_id: Optional[int] = None
class FastCanvas(tk.Canvas):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.active_rectangles = []
self.active_lines = []
self.active_texts = []
self.inactive_rectangles = []
self.inactive_lines = []
self.inactive_texts = []
@property
def n_active_rectangles(self):
return len(self.active_rectangles)
@property
def n_active_lines(self):
return len(self.active_lines)
@property
def n_active_texts(self):
return len(self.active_texts)
def invalidate(self):
"""Sets all rectangles, lines, and texts to not be active,
so they can be reused.
"""
for rect in self.active_rectangles:
self.itemconfigure(rect.tk_id, state=tk.HIDDEN)
for line in self.active_lines:
self.itemconfigure(line.tk_id, state=tk.HIDDEN)
for text in self.active_texts:
self.itemconfigure(text.tk_id, state=tk.HIDDEN)
self.inactive_rectangles = self.active_rectangles
self.active_rectangles = []
self.inactive_lines = self.active_lines
self.active_lines = []
self.inactive_texts = self.active_texts
self.active_texts = []
def create_item(
self,
item,
active_list,
inactive_list,
create_func,
*args,
**kwargs
):
if inactive_list:
item = inactive_list.pop()
item.args = args
item.kwargs = kwargs
self.itemconfigure(item.tk_id, state=tk.NORMAL)
super().coords(item.tk_id, *args)
super().itemconfig(item.tk_id, **kwargs)
self.tag_raise(item.tk_id) # draw order matters here...
else:
item = item(args, kwargs, create_func(*args, **kwargs))
active_list.append(item)
return item.tk_id
def create_rectangle(self, *args, **kwargs):
"""Creates a rectangle. Tries to reuse old rectangles.
If all rectangles are in use, creates a new one.
"""
return self.create_item(Rectangle, self.active_rectangles, self.inactive_rectangles, super().create_rectangle, *args, **kwargs)
def create_line(self, *args, **kwargs):
"""Creates a line. Tries to reuse old lines.
If all lines are in use, creates a new one.
"""
return self.create_item(Line, self.active_lines, self.inactive_lines, super().create_line, *args, **kwargs)
def create_text(self, *args, **kwargs):
"""Creates a text. Tries to reuse old texts.
If all texts are in use, creates a new one.
"""
return self.create_item(Text, self.active_texts, self.inactive_texts, super().create_text, *args, **kwargs)