【问题标题】:Pygame - blitting for a preview picturePygame - 预览图片
【发布时间】:2014-04-19 15:19:03
【问题描述】:

首先,这是一项学校作业,所以我想坦率地说。其次,我只是在寻求有关该方法的建议,以及对代码的可能帮助。我正在使用我们书中的一些预先存在的代码进行 MSPAINT 样式的克隆。代码中已经有了按鼠标键1时draw.line的用法。老师要我们增加画圆或矩形的能力。我正在研究圆圈部分,并且我已经弄清楚(感谢这里的论坛)如何实现我想对 MOUSEBUTTONDOWN 和 MOUSEBUTTONUP 事件做的事情。这给我带来了一个新问题。我该怎么做blit 然后擦除然后 blit 预览圆圈,直到达到用户想要的大小,然后他们释放 MOUSEBUTTON 并查看最终 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

非常感谢

-本

【问题讨论】:

  • 好吧,所以我在这里做了更多调查,并找到了我对 mousebutton 事件的答案,但它现在让我想到了另一个问题。我如何在 mousebuttonup 事件之前将圆圈作为预览?跨度>
  • 如果您的问题发生了变化,您应该edit 它来表示您现在的实际问题是根据需要添加/删除信息。
  • 马上就做!

标签: python python-2.7 pygame


【解决方案1】:

所以经过一番思考,这是我使用 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

【讨论】:

  • 你的例子真的帮助了我......我喜欢圆位置的 x,y 坐标的实现等于鼠标坐标..它使使用元组更容易..并在鼠标存储位置的那个元组上绘制圆圈,并在释放按钮时鼠标移动的距离......这就是我喜欢这个网站的原因!非常感谢!!!
  • 没问题的朋友 :) 与往常一样,如果您认为某个答案有帮助,您可以随时用勾号标记它,以便其他用户知道您的问题已经解决!
【解决方案2】:

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


对于圆形绘制模式,您希望在用户按下鼠标按钮时复制屏幕表面,然后每帧将该副本blit 到屏幕上。

然后在该副本上画出你的圆圈。这样,您基本上可以“擦除”临时圈子。


这是一个简单的例子。按 SPACE 在不同的模式(绘制、圆形、矩形)和 TAB 之间循环切换不同的颜色:

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)

【讨论】:

  • Dominic..谢谢你的例子!我从您的示例中了解到,我可以创建具有允许我调用鼠标位置和/或鼠标输入以在绘制函数中使用的函数的类。我可以假设这将有助于提高系统速度,因为您没有将其包含在主循环!
猜你喜欢
  • 1970-01-01
  • 2018-04-23
  • 2014-08-06
  • 1970-01-01
  • 1970-01-01
  • 2014-11-04
  • 2020-06-25
  • 2014-05-22
  • 1970-01-01
相关资源
最近更新 更多