Python Pygame-预览图片的blitting

Python Pygame-预览图片的blitting,python,python-2.7,pygame,Python,Python 2.7,Pygame,首先,这是一项学校作业,所以我想提前说明。第二,我只是在征求关于方法的建议,可能的代码帮助。我正在使用我们书中的一些预先存在的代码进行MSPAINT风格的克隆。当按下鼠标按钮1时,该代码已使用draw.line。老师想让我们增加画圆或矩形的能力。我正在研究circle部分,我已经想出了(感谢这里的论坛)如何实现我想对MOUSEBUTTONDOWN和MOUSEBUTTONUP事件执行的操作。。这给我带来了一个新问题。。我该如何删除然后删除,然后预览一个圆圈,直到它的大小是用户想要的,他们释放鼠标按

首先,这是一项学校作业,所以我想提前说明。第二,我只是在征求关于方法的建议,可能的代码帮助。我正在使用我们书中的一些预先存在的代码进行MSPAINT风格的克隆。当按下鼠标按钮1时,该代码已使用draw.line。老师想让我们增加画圆或矩形的能力。我正在研究circle部分,我已经想出了(感谢这里的论坛)如何实现我想对MOUSEBUTTONDOWN和MOUSEBUTTONUP事件执行的操作。。这给我带来了一个新问题。。我该如何删除然后删除,然后预览一个圆圈,直到它的大小是用户想要的,他们释放鼠标按钮,并查看最终的blit

while keepGoing:
    clock.tick(30)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keepGoing = False
        elif event.type == pygame.MOUSEMOTION:
            lineEnd = pygame.mouse.get_pos()
            if pygame.mouse.get_pressed() == (1,0,0):
                pygame.draw.line(background, drawColor, lineStart, lineEnd, lineWidth)
            lineStart = lineEnd
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
                    circleStart = pygame.mouse.get_pos()
        elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: 
                    circleEnd = pygame.mouse.get_pos()
                    size = (circleEnd[0] - circleStart[0])
                    pygame.draw.circle(background, drawColor, circleStart, size, lineWidth)
        elif event.type == pygame.KEYDOWN:
            myData = (event, background, drawColor, lineWidth, keepGoing)
            myData = checkKeys(myData)
            event, background, drawColor, lineWidth, keepGoing) = myData
非常感谢


-Ben

经过思考,这是我用pygame想出的最好的解决方案。告诉我你的想法,以及它是否对你有帮助

import pygame,sys,math #---- Import modules we will need

pygame.init() #---- Initialize the module

def get_rad(origin_x,origin_y,x,y): #----- Returns the appropriate radius
    return math.sqrt((origin_x - x)**2 + (origin_y - y)**2) #----- Distance between 2
                                                            #----- points

screen = pygame.display.set_mode((400,400)) #----- Sets up the screen
clock  = pygame.time.Clock() #------- Sets up the clock

mouse_button = 0 #--------- This variable is used to determine whether a mouse button
                 #--------- has been pressed

draw_final_circle = False #---------- This variable lets us know that we should draw the 
                          #---------- final circle

while True: #------ main loop

    clock.tick(60) #------ Limit the Fps

    mouse_button0  = mouse_button #-------- This variable holds the previous value of 
                                  #-------- mouse_button(it will be useful later)

    mouse_x,mouse_y = pygame.mouse.get_pos() #----- Get the mosue coordinates

    for e in pygame.event.get(): #---- Cycle through events

        if e.type == pygame.QUIT: pygame.quit();sys.exit() #--Quit when window is closed

        if e.type == pygame.MOUSEBUTTONDOWN: #---- If the mouse button is pressed
            if mouse_button == 0: #---- if the mouse button is released
                mouse_button = 1 #----- set it to pressed basically
                originx,originy = mouse_x,mouse_y #---- keep the mouse_x,mouse_y pos

        if e.type == pygame.MOUSEBUTTONUP: #---- if the mouse button is released
             if mouse_button == 1: #-------- if it is pressed
                 mouse_button = 0 #--------- set it to released

    screen.fill((255,255,255)) #---- clear the screen


    #-------- If a mouse button is pressed and a circle can be drawn (rad>width) ------#
    if mouse_button == 1 and get_rad(originx,originy,mouse_x,mouse_y) > 1:

        rad = int(get_rad(originx,originy,mouse_x,mouse_y)) #---- get the radius(as int)
        pos = mouse_x,mouse_y
        pygame.draw.circle(screen,(0,0,0),pos,rad,1) #--- draw the circle

    #----------------------------------------------------------------------------------#


    #---------- if the button is released but in the previous loop it was pressed -----#
    if mouse_button == 0 and mouse_button0 == 1:

        draw_final_circle = True #----- set the final circle boolean to True

    if draw_final_circle: #----- if the final circle is decided
        pygame.draw.circle(screen,(0,0,0),pos,rad,1) #---- keep drawing it 

    pygame.display.flip() #----- flip the buffer

我建议您将绘图程序的不同模式实现到表示当前模式及其状态的不同类中。这样,实现不同的模式变得非常容易


对于圆形绘图模式,您希望在用户按下鼠标按钮时复制屏幕表面,并在每一帧将该复制复制复制到屏幕上

然后在副本上画圆圈。这样,基本上可以“擦除”临时圆圈


这里有一个简单的例子。按空格键可在不同模式(绘制、圆形、矩形)和制表符之间循环使用不同的颜色:

import pygame
from math import hypot
from itertools import cycle
from operator import itemgetter

pygame.init()
screen = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

colors = cycle(sorted(pygame.color.THECOLORS.iteritems(), key=itemgetter(0)))
color = next(colors)[1]

class DrawMode(object):
    def __init__(self):
        self.last = None
    def handle(self, e):
        if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
            self.last = pygame.mouse.get_pos()
        if e.type == pygame.MOUSEBUTTONUP and e.button == 1:
            self.last = None
    def draw(self, screen):
        pos = pygame.mouse.get_pos()
        if self.last:
            pygame.draw.line(screen, color, self.last, pos)
            self.last = pos

class ClickReleaseMode(object):
    def __init__(self):
        self.tmp = None
        self.start = None
    def handle(self, e):
        if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
            self.start = pygame.mouse.get_pos()
        if e.type == pygame.MOUSEBUTTONUP and e.button == 1:
            self.start = self.tmp = None
    def draw(self, screen):
        if not self.tmp:
            self.tmp = screen.copy()

        pos = pygame.mouse.get_pos()
        screen.blit(self.tmp, (0,0))
        if self.start:
            self.do_draw(screen, pos)

class CircleMode(ClickReleaseMode):
    def __init__(self):
        super(CircleMode, self).__init__()

    def do_draw(self, screen, pos):
        r = hypot(pos[0] - self.start[0], pos[1] - self.start[1])
        if r >= 2:
            pygame.draw.circle(screen, color, self.start, int(r), 2)

class RectMode(ClickReleaseMode):#
    def __init__(self):
        super(RectMode, self).__init__()

    def do_draw(self, screen, pos):
        p = pos[0] - self.start[0], pos[1] - self.start[1]
        pygame.draw.rect(screen, color, pygame.Rect(self.start, p), 2)

quit = False
modes = cycle((DrawMode, CircleMode, RectMode))
mode = next(modes)()
while not quit:
    quit = pygame.event.get(pygame.QUIT)
    for e in pygame.event.get():
        if e.type == pygame.KEYDOWN:
            if e.key == pygame.K_SPACE:
                mode = next(modes)()
                print 'enter', mode.__class__.__name__
            if e.key == pygame.K_TAB:
                name, color = next(colors)
                print 'changing color to', name, color
        mode.handle(e)
    mode.draw(screen)
    pygame.display.flip()
    clock.tick(60)

好的,我在这里做了更多的调查,找到了我关于鼠标按钮事件的答案,但现在我要问另一个问题。我如何在鼠标按钮事件之前预览圆圈?如果您的问题发生了变化,你应该使用它来表示你现在的实际问题是什么,根据需要添加/删除信息。我现在就做!你的例子真的帮助了我。。。我喜欢圆位置的x、y坐标与鼠标坐标相等。。这使得使用元组更容易。。并在鼠标存储位置的元组处绘制圆圈,以及释放按钮时鼠标移动的距离。。。这就是为什么我喜欢这个网站!!!非常感谢!!!没问题,伙计:)如果你认为某个答案对你有帮助,你可以总是用勾号来标记它,这样其他用户就可以知道你的问题已经解决了!多米尼克,谢谢你的例子!我从您的示例中了解到,我可以使用函数创建类,该函数允许我调用鼠标位置和/或鼠标输入,以便在绘图函数中使用。。我可以假设这将有助于提高系统速度,因为您没有将其包含在主循环中!