写在前面
这是将近一年前学校开设的Python高级语言程序课上的一次作业,最近太久没打代码所以又翻出来重新温习了一遍,希望对自己以后做项目开发软件设计方面有所帮助
创建画笔类
橡皮擦视作颜色为白的笔即可
我们给画笔一个drawing开关记录现在是否在画画(也就是当我们在画布上按下鼠标左键时drawing变为True)同时记录笔刷的上一位置也即las_pos
当我们捕捉到鼠标移动时,我们开始绘制曲线,我们希望笔刷画出的轨迹相对圆润平滑,所以我们在las_pos以及当前pos的连线上等间距选取圆心,并以当前画笔大小(size)为半径作实心圆
最后当我们捕捉到鼠标左键松开时,drawing开关关闭即可
class Brush():
def __init__(self,screen):
self.color=(0,0,0)
self.screen=screen
self.drawing=False
self.size=1
self.laspos=None
self.lascol=(0,0,0)
self.p_or_e=True
def start(self,pos):
self.drawing=True
self.laspos=pos
def close(self):
self.drawing=False
def set_size(self,size):
if size>50:
size=50
elif size<1:
size=1
self.size=size
def get_size(self):
return self.size
def getline(self,pos):
lenx=pos[0]-self.laspos[0]
leny=pos[1]-self.laspos[1]
length=math.sqrt(lenx**2+leny**2)
cosx=lenx/length
sinx=leny/length
points=[]
for i in range(int(length)):
points.append((self.laspos[0]+i*cosx,self.laspos[1]+i*sinx))
points.append((self.laspos[0]+length*cosx,self.laspos[1]+length*sinx))
return points
def Draw(self,pos):
if self.drawing==True:
for p in self.getline(pos):
pygame.draw.circle(self.screen,self.color,p,self.size)
self.laspos=pos
创建菜单栏
菜单栏上设计了吸色盘,笔刷变大变小按钮,选取橡皮或笔刷的按钮
pygame给了我们Rect也就是矩形这个非常方便的对象
rect =pygame.Rect(left,top,width,height)
同时也给了 collidepoint 函数可以很便捷地判断某一位置是否在当前矩形范围内
吸色盘只需设计多个矩形(这里用了8*2)并在其中填充相应颜色就好,当鼠标左键按下时根据相应坐标就能知道选取了什么颜色
其余部分也都一样,各自设置一下对应的矩形位置就能判断点击了哪里
class Menu():
def __init__(self,screen,brush):
self.screen=screen
self.brush=brush
self.colors=[
(0xff, 0x00, 0xff), (0x80, 0x00, 0x80),
(0x00, 0x00, 0xff), (0x00, 0x00, 0x80),
(0x00, 0xff, 0xff), (0x00, 0x80, 0x80),
(0x00, 0xff, 0x00), (0x00, 0x80, 0x00),
(0xff, 0xff, 0x00), (0x80, 0x80, 0x00),
(0xff, 0x00, 0x00), (0x80, 0x00, 0x00),
(0xc0, 0xc0, 0xc0), (0xff, 0xff, 0xff),
(0x00, 0x00, 0x00), (0x80, 0x80, 0x80),
]
self.color_rec=[]
for (i,col) in enumerate(self.colors):
if i%2==0:
rect=pygame.Rect(10,10+i//2+32*(i//2),32,32)
else:
rect=pygame.Rect(43,10+i//2+32*(i//2),32,32)
self.color_rec.append(rect)
self.pen=pygame.image.load('./img/pen.png').convert_alpha()
self.plus=pygame.image.load('./img/plus.png').convert_alpha()
self.minus=pygame.image.load('./img/minus.png').convert_alpha()
self.eraser=pygame.image.load('./img/eraser.png').convert_alpha()
self.pen_rec=Rect(10,275,28,28)
self.plus_rec=Rect(10,320,28,28)
self.minus_rec=Rect(40,320,28,28)
self.eraser_rec=Rect(40,275,28,28)
def draw(self):
self.screen.blit(self.pen,self.pen_rec.topleft)
self.screen.blit(self.eraser,self.eraser_rec.topleft)
self.screen.blit(self.plus,self.plus_rec.topleft)
self.screen.blit(self.minus,self.minus_rec.topleft)
for (i,col) in enumerate(self.color_rec):
pygame.draw.rect(self.screen,self.colors[i],col)
def click_button(self,pos):
for (i,col) in enumerate(self.color_rec):
if col.collidepoint(pos):
self.brush.p_or_e=True
self.brush.color=self.colors[i]
self.brush.lascol=self.colors[i]
return True
if self.pen_rec.collidepoint(pos):
if self.brush.p_or_e==False:
self.brush.p_or_e=True
self.brush.color=self.brush.lascol
return True
if self.eraser_rec.collidepoint(pos):
if self.brush.p_or_e==True:
self.brush.p_or_e=False
self.brush.color=(255,255,255)
return True
if self.plus_rec.collidepoint(pos):
self.brush.set_size(self.brush.get_size()+1)
return True
if self.minus_rec.collidepoint(pos):
self.brush.set_size(self.brush.get_size()-1)
return True
return False
画板
在这部分定义了快捷键, esc 清空屏幕, ctrl+z 撤销, ctrl+s 保存。
先使用 key.get_pressed 捕获按下的键并保存在key_pressed中:
key_pressed = pygame.key.get_pressed()
判断组合键只需keypressed[K_LCTRL] _与_keypressed[K_letter]同时判定为true即可
esc_即把画板全涂成白色, _ctrl+s 即将当前图像按照 “Draw+tot”的格式保存即可
对于撤销操作,我们只需开一个栈:
las_screen=[]
然后依次保存每次动笔前的surface对象,按下 ctrl+z 使用 blit 函数覆盖当前界面并弹栈
self.screen.blit(las_screen[len(las_screen)-1],(0,0))
las_screen.pop()
画板部分代码:
class Painter():
def __init__(self):
pygame.display.set_caption('Painter')
self.clock=pygame.time.Clock()
self.screen=pygame.display.set_mode(fbl,0,32)
self.brush=Brush(self.screen)
self.menu=Menu(self.screen,self.brush)
def run(self):
tot=1
self.screen.fill((255,255,255))
while True:
self.clock.tick(60)
for event in pygame.event.get():
if event.type==QUIT:
exit()
elif event.type==MOUSEBUTTONDOWN:
if self.menu.click_button(event.pos):
pass
elif event.pos[0]>=0 and event.pos[1]fbl[0] and event.pos[1]>=0 and event.pos[1]fbl[1]:
las_screen.append(self.screen.copy())
self.brush.start(event.pos)
elif event.type==MOUSEMOTION:
self.brush.Draw(event.pos)
elif event.type==MOUSEBUTTONUP:
self.brush.close()
elif event.type==KEYDOWN:
key_pressed = pygame.key.get_pressed()
if key_pressed[K_LCTRL] and key_pressed[K_s]:
pygame.image.save(self.screen,'Draw'+str(tot)+'.png')
tot+=1
elif key_pressed[K_LCTRL] and key_pressed[K_z]:
if len(las_screen)==0:
pass
else:
self.screen.blit(las_screen[len(las_screen)-1],(0,0))
las_screen.pop()
elif event.key==K_ESCAPE:
las_screen.append(self.screen.copy())
self.screen.fill((255,255,255))
self.menu.draw()
pygame.display.update()
最终效果
Original: https://blog.csdn.net/qq_39562371/article/details/125154031
Author: Checkmate_Ril
Title: pygame实现的GUI画板
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/780394/
转载文章受原作者版权保护。转载请注明原作者出处!