Прикреплённый файл «2014-02-21-dumbedit.py»
Загрузка 1 #!/usr/bin/env python
2 # coding: utf
3 '''
4 «Ухудшенный графический редактор». Написать программу обработки изображений со следующими возможностями:
5 Загрузка файла (нажатие клавиши "l", имя файла содержится в буфере обмена, в случае неудачи выводить предупреждение)
6 Запись файла с тем же именем ("s")
7 Рисование мышью (клавиша "d" + изменение курсора)
8
9 <!> Нарисовать свой курсор
10 Поворот и изменение размера картинки (клавиша "r"): первая точка — центр вращения, затем поворот при нажатой кнопке (если нажата правая --- изменение размера). Курсор тоже менять
11 '''
12
13 import pygame, sys, os
14 from pygame.locals import *
15 from math import *
16
17 os.chdir(os.path.expanduser("~"))
18 pygame.init()
19 NoEvent = pygame.event.Event(NOEVENT)
20
21 def fullcursor(spot, data, black='X', white='.', xor='o'):
22 c = pygame.cursors.compile(data, black, white, xor)
23 return ((len(data[0]),len(data)), spot) + c
24
25 class BasicState:
26 cursor = pygame.cursors.arrow
27
28 def __init__(self):
29 pass
30
31 def loop(self, event):
32 if event.type == QUIT:
33 game.exit = True
34 elif event.type == KEYDOWN and event.unicode in u"Ff":
35 pygame.display.toggle_fullscreen()
36 else:
37 return event
38 return NoEvent
39
40 def redraw(self):
41 game.screen.blit(game.back, (0,0))
42 r = game.img.get_rect()
43 r.center = game.screen.get_rect().center
44 game.screen.blit(game.img, r)
45
46 class LoadState(BasicState):
47 cursor = fullcursor( (0,0), (
48 " XXXXXXXXXXXXXXXXXXXXXX ",
49 "XXXXXXXXXXXXXXXXXXXXXXXX",
50 "XX ........... XX",
51 "XX ........... XX",
52 "XX ........... XX",
53 "XX ........... XX",
54 "XX ........... XX",
55 "XX XX",
56 "XX oooo XX",
57 "XX oooooo XX",
58 "XX oooooooo XX",
59 "XX oooooooo XX",
60 "XX oooooooo XX",
61 "XX oooooooo XX",
62 "XX oooooo XX",
63 "XX oooo XX",
64 "XX XX",
65 "XX XX",
66 "XX XX",
67 "XX XX",
68 "XX XX",
69 "XX XX",
70 "XXXXXXXXXXXXXXXXXXXXXXXX",
71 " XXXXXXXXXXXXXXXXXXXXXX ",
72 ))
73 scrap = ""
74
75 def __init__(self):
76 BasicState.__init__(self)
77 self.scrap = ""
78
79 def action(self, text):
80 try:
81 img = pygame.image.load(text)
82 if not img: raise Error
83 except:
84 print >> sys.stderr, "Cannot load file '{}'".format(text)
85 return False
86 game.imgname, game.img = text, img
87 return game.imgname
88
89 def loop(self, event):
90 event = BasicState.loop(self,event)
91 if self.scrap:
92 if self.action(self.scrap):
93 game.setstate(MainState)
94 return NoEvent
95 else:
96 self.scrap = ""
97 if event.type in (KEYDOWN, MOUSEBUTTONDOWN):
98 game.setstate(MainState)
99 elif event.type == MOUSEMOTION:
100 text = pygame.scrap.get("TEXT").strip()
101 if text and text != self.scrap:
102 self.scrap = text
103 else:
104 return event
105 return NoEvent
106
107 class SaveState(LoadState):
108 def __init__(self):
109 LoadState.__init__(self)
110 self.scrap = game.imgname
111
112 def action(self, text):
113 try:
114 pygame.image.save(game.screen, text)
115 print >> sys.stderr, "Saving to '{}'".format(text)
116 except:
117 print >> sys.stderr, "Cannot write to file '{}'".format(text)
118 return False
119 game.imgname = text
120 return game.imgname
121
122 class DrawState(BasicState):
123 cursor = pygame.cursors.broken_x
124 def __init__(self):
125 BasicState.__init__(self)
126 self.pos=None
127
128 def loop(self, event):
129 event = BasicState.loop(self, event)
130 if event.type == MOUSEMOTION:
131 if self.pos:
132 pygame.draw.aaline(game.back, tan, self.pos, event.pos)
133 self.pos = event.pos
134 elif event.type == MOUSEBUTTONUP:
135 game.setstate(MainState)
136
137 class RotoState(BasicState):
138 cursor = pygame.cursors.diamond
139 def __init__(self):
140 BasicState.__init__(self)
141 self.pos = game.screen.get_rect().center
142 self.back = game.screen
143 self.img = game.screen.copy()
144
145 def loop(self, event):
146 events=[BasicState.loop(self, event)]+pygame.event.get()
147 pos=self.pos
148 for event in events:
149 if event.type == MOUSEMOTION:
150 pos = event.pos
151 elif event.type == MOUSEBUTTONUP:
152 pass
153 elif event.type == MOUSEBUTTONDOWN:
154 game.setstate(MainState)
155 break
156 else:
157 game.img = self.back
158 game.setstate(MainState)
159 return event
160 if pos != self.pos:
161 # TODO определить угол и расстояние от центра, а не x|y
162 sz, rot = float(pos[0])/self.pos[0], float(pos[1])-self.pos[1]
163 game.img = pygame.transform.rotozoom(self.img, rot, sz)
164 return NoEvent
165
166 class MainState(BasicState):
167 def loop(self, event):
168 event = BasicState.loop(self,event)
169 if event.type == KEYDOWN:
170 if event.unicode in u"Ll":
171 game.setstate(LoadState)
172 elif event.unicode in u"Ss":
173 game.setstate(SaveState)
174 elif event.type == MOUSEBUTTONDOWN:
175 if event.button == 1:
176 game.setstate(DrawState)
177 elif event.button == 3:
178 game.setstate(RotoState)
179 else:
180 return event
181 return NoEvent
182
183 class Game:
184 def __init__(self):
185 self.size = 800,600
186 self.screen = pygame.display.set_mode(self.size)
187 self.screen.fill((0,0,0))
188 self.img = pygame.Surface((0,0))
189 self.imgname = ""
190 self.back = self.screen.copy()
191 self.setstate(MainState)
192 self.exit = False
193
194 def setstate(self, state):
195 self.state = state()
196 pygame.mouse.set_cursor(*self.state.cursor)
197
198 game = Game()
199
200 pygame.scrap.init()
201 pygame.scrap.set_mode(SCRAP_SELECTION)
202 tan = pygame.Color("tan")
203 imgname = ""
204 state, pos = "base", (0,0)
205 while not game.exit:
206 event = pygame.event.wait()
207 game.state.loop(event)
208 game.state.redraw()
209 pygame.display.flip()
Прикреплённые файлы
Для ссылки на прикреплённый файл в тексте страницы напишите attachment:имяфайла, как показано ниже в списке файлов. Не используйте URL из ссылки «[получить]», так как он чисто внутренний и может измениться.Вам нельзя прикреплять файлы к этой странице.