Прикреплённый файл «win.py»
Загрузка 1 #!/usr/bin/python
2 # coding: utf-8
3 # vim: expandtab:ts=4:sw=4
4 '''
5 Написать «оконную систему», состоящую из классов
6
7 * Экран (контейнер окон, позволяет манипулировать окнами)
8 o Список окон, определение окна-получателя события
9 o Глубина окон, изменение глубины окон
10 o Перемещение и изменение размера окон
11 * Окно (позволяет манипулировать своим содержимым)
12
13 win.py: классы
14 '''
15
16 import pygame, sys
17
18 class descriptor:
19 '''Window descritor'''
20 def __init__(self, rect, window, mode=["basic"], **argn):
21 '''Create a window descriptor object with defaut basic mode'''
22 self.rect=rect
23 self.window=window
24 if type(mode) is str:
25 self.mode=[mode]
26 else:
27 self.mode=mode or ["basic"]
28
29 class basic_screen:
30 '''Windows container'''
31 def __init__(self, surface, bg=(0,0,0)):
32 '''Create a screen using given surface'''
33 self.surface = surface
34 self.windows = []
35 self.immed = [] # events to be handled immediately
36 self.hanled = [] # events we handle if no child doesn.t
37 self.bg = bg
38
39 def append(self, rect, mode, creator, *args, **argn):
40 '''Call creator() with *args, **argn
41 to produce a window (of mode type) on rect-sized subsurface
42 and put the window in the top'''
43 wnd = creator(self.surface.subsurface(rect), *args, **argn)
44 self.windows.append(descriptor(rect,wnd,mode))
45 return wnd
46
47 def pop(self, index=-1):
48 '''Unregister corresponded window and return it'''
49 if self.windows:
50 return self.windows.pop(index)
51 else:
52 return None
53
54 def clear(self):
55 '''Draw initial screen's surface without all windows'''
56 if self.bg:
57 self.surface.fill(self.bg)
58
59 def redraw(self):
60 '''Redraw all the contents'''
61 self.clear()
62 for wnd in self.windows:
63 wnd.window.redraw()
64
65 def up(self, index):
66 '''Put indexed window deeper'''
67 if len(self.windows) > 1 and index < len(self.windows)-1:
68 index+=1
69 self.windows[index-1],self.windows[index]= \
70 self.windows[index], self.windows[index-1]
71 return index
72
73 def down(self, index):
74 '''Pull indexed window upper'''
75 if len(self.windows) > 1 and index > 0:
76 self.windows[index-1],self.windows[index]= \
77 self.windows[index] ,self.windows[index-1]
78 index-=1
79 return index
80
81 def top(self, index):
82 '''Bring indexed window to the top'''
83 if index < len(self.windows):
84 w=self.windows.pop(index)
85 self.windows.append(w)
86
87 def locate(self, pos):
88 '''Locate a window than owns visible pos coordinate.
89 If not found return -1'''
90 for i in xrange(len(self.windows)-1, -1, -1):
91 if self.windows[i].rect.collidepoint(pos):
92 return i
93 return -1
94
95 def handler(self, event, pos):
96 '''Handle an event that not correspond any window'''
97 return False
98
99 def proceed(self, event, pos):
100 '''Check if the event is to be handled by certain window
101 and let the window do it. If no appropriete windows found
102 or window nas no idea how to handle an event, handle it manually.
103 Return false if no event handler is provided.'''
104 ret=False
105 if event in self.immed:
106 ret=self.handler(event, pos)
107 if not ret:
108 index=self.locate(pos)
109 if index>=0:
110 wpos=(pos[0]-self.windows[index].rect.left,pos[1]-self.windows[index].rect.top)
111 ret=self.windows[index].window.proceed(event,wpos)
112 return ret or self.handler(event, pos)
113
114 def renew(self,surface):
115 '''Stck window to a new surface'''
116 self.surface = surface
117 for wnd in self.windows:
118 wnd.window.renew(surface.subsurface(wnd.rect))
119
120 class simple_screen(basic_screen):
121 '''Screen with simple window management'''
122 def __init__(self, *argv, **argn):
123 '''Additional parameters:
124 titlebg: title background
125 titlefg: title foreground
126 borderwidth: width of border line
127 bordercolor: base color of border (3D effect applied)
128 '''
129 self.titlebg=argn.get('titlebg',(0,32,64))
130 self.titlefg=argn.get('titlefg',(255,248,128))
131 self.borderwidth=argn.get('borderwidth',2)
132 self.bordercolor=argn.get('bordercolor',(128,128,128))
133 self.titlesize=14
134 basic_screen.__init__(self, *argv, **argn)
135 self.immed.extend([pygame.MOUSEMOTION, pygame.MOUSEBUTTONDOWN])
136 self.focus=-1
137
138 def handler(self, event, pos):
139 '''
140 pygame.MOUSEMOTION with button1 down -- move focused window
141 pygame.MOUSEBUTTONDOWN with button1 -- focus a window
142 with buttion4/5 -- raise/lower a window
143 '''
144 ret=False
145 if event.type == pygame.MOUSEMOTION and event.buttons[0]:
146 if self.focus >= 0:
147 nrect = self.windows[self.focus].rect.move(event.rel)
148 if self.surface.get_rect().contains(nrect):
149 self.windows[self.focus].rect.move_ip(event.rel)
150 self.windows[self.focus].window.renew(self.surface.subsurface(self.windows[self.focus].rect))
151 ret=True
152 elif event.type == pygame.MOUSEBUTTONDOWN:
153 if event.button == 1:
154 index = self.locate(pos)
155 if index >=0 and index != self.focus:
156 self.focus=index
157 ret=True
158 elif event.button == 4:
159 self.focus=self.up(self.locate(pos))
160 ret=True
161 elif event.button == 5:
162 self.focus=self.down(self.locate(pos))
163 ret=True
164 return ret
165
166 def highlight_window(self, index):
167 '''Draw 4 black-white circles to merk a window'''
168 for center in [ self.windows[index].rect.topleft,
169 self.windows[index].rect.bottomleft,
170 self.windows[index].rect.topright,
171 self.windows[index].rect.bottomright ]:
172 pygame.draw.circle(self.surface, (0,0,0), center, 4)
173 pygame.draw.circle(self.surface, (255,255,255), center, 3)
174
175 def pop(self, index=-1):
176 w=basic_screen.pop(self,index)
177 if w:
178 # TODO not to lose focus if non-focused window is deleted
179 self.focus=-1
180 return w
181
182 def redraw(self):
183 '''Redraw all windows then highlight focused window, if any'''
184 basic_screen.redraw(self)
185 if self.focus >=0:
186 self.highlight_window(self.focus)
187
188 class basic_window:
189 '''Basic type window'''
190 def __init__(self, surface, bg=(0,0,0)):
191 '''Create a window based on given surface
192 if bg is None, make transparent window'''
193 self.surface = surface
194 self.bg = bg
195
196 def renew(self,surface):
197 '''Stck window to a new surface'''
198 self.surface = surface
199
200 def redraw(self):
201 if self.bg:
202 self.surface.fill(self.bg)
203
204 def proceed(self, event, pos):
205 return False
206
207 def drawable(self):
208 return self.surface
209
210 class text_window(basic_window):
211 '''Window with text inside'''
212 def __init__(self, surface, bg=(0,0,0), fg=(200,200,200), text='', font="dejavusans", size=14):
213 basic_window.__init__(self, surface, bg)
214 self.fg=fg
215 self.text=text
216 if type(font) is pygame.font.Font:
217 self.font = font
218 else:
219 if not pygame.font.get_init:
220 pygame.font.init()
221 self.font=pygame.font.SysFont(font, size)
222
223 def redraw(self):
224 basic_window.redraw(self)
225 self.surface.blit(self.font.render(self.text,True,self.fg),(0,0))
226
227 class screen_window(basic_screen):
228 '''Window with title and frame, screen internal'''
229 def __init__(self, surface, screen, title):
230 '''Use parent simple_creen defaults for title and frame'''
231 basic_screen.__init__(self, surface, screen.bg)
232 self.bordercolor, self.borderwidth = screen.bordercolor, screen.borderwidth
233 self.title = title
234 self.parent = screen
235 trect=pygame.Rect(screen.borderwidth, screen.borderwidth,
236 surface.get_width()-2*screen.borderwidth, screen.titlesize+2*screen.borderwidth)
237
238 self.append(trect, "text", text_window, text=title,
239 bg=screen.titlebg, fg=screen.titlefg, size=screen.titlesize)
240 drect=pygame.Rect(screen.borderwidth, trect.height+2*screen.borderwidth,
241 trect.width, surface.get_height()-trect.height-3*screen.borderwidth)
242 self.append(drect, "basic", basic_window, bg=screen.bg)
243
244 def redraw(self):
245 basic_screen.redraw(self)
246 rect=self.surface.get_rect()
247 x,y,w,h=rect.topleft+rect.size
248 line=((x,y), (x+w-self.borderwidth,y), (x+w-self.borderwidth,y+h-self.borderwidth), (x,y+h-self.borderwidth))
249 pygame.draw.lines(self.surface, self.bordercolor, True, line, self.borderwidth)
250 middle=self.windows[0].rect.height+self.borderwidth
251 pygame.draw.line(self.surface, self.bordercolor, (self.borderwidth,middle), (rect.width-self.borderwidth,middle), self.borderwidth)
252
253 def drawable(self):
254 return self.windows[1].window.surface
Прикреплённые файлы
Для ссылки на прикреплённый файл в тексте страницы напишите attachment:имяфайла, как показано ниже в списке файлов. Не используйте URL из ссылки «[получить]», так как он чисто внутренний и может измениться.- [получить | показать] (2011-09-26 11:35:29, 9.5 KB) [[attachment:win.py]]
- [получить | показать] (2011-09-26 11:35:29, 2.2 KB) [[attachment:winrun.py]]
Вам нельзя прикреплять файлы к этой странице.