如何在Python/Pygame中创建按钮?

9
我正在使用pygame制作游戏,希望在第一个屏幕上添加按钮,可以点击以下选项:(i)开始游戏,(ii)加载新的包含说明的屏幕,和(iii)退出程序。

我在网上找到了制作按钮的代码,但是我不太理解它(我不擅长面向对象编程)。如果您能解释一下这段代码在做什么,那就太棒了。此外,当我尝试使用文件路径打开计算机上的文件时,我收到“sh: filepath: Permission denied”错误提示,我不知道该怎么解决。

#load_image is used in most pygame programs for loading images
def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', fullname
        raise SystemExit, message
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()
class Button(pygame.sprite.Sprite):
    """Class used to create a button, use setCords to set 
        position of topleft corner. Method pressed() returns
        a boolean and should be called inside the input loop."""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_image('button.png', -1)

    def setCords(self,x,y):
        self.rect.topleft = x,y

    def pressed(self,mouse):
        if mouse[0] > self.rect.topleft[0]:
            if mouse[1] > self.rect.topleft[1]:
                if mouse[0] < self.rect.bottomright[0]:
                    if mouse[1] < self.rect.bottomright[1]:
                        return True
                    else: return False
                else: return False
            else: return False
        else: return False
def main():
    button = Button() #Button class is created
    button.setCords(200,200) #Button is displayed at 200,200
    while 1:
        for event in pygame.event.get():
            if event.type == MOUSEBUTTONDOWN:
                mouse = pygame.mouse.get_pos()
                if button.pressed(mouse):   #Button's pressed method is called
                    print ('button hit')
if __name__ == '__main__': main()

感谢任何能够帮助我的人。
6个回答

12

我没有给你一个代码示例,但是我会这么做:

  1. 创建一个 Button 类,将要放在按钮上的文本作为构造函数参数
    1. 创建一个 PyGame 表面,可以是图像或填充 Rect
    2. 使用 Pygame 中的 Font.Render 来渲染出文字
  2. 将其 blit 到游戏屏幕上,并保存该 rect。
  3. 检查,在鼠标点击时,看看 mouse.get_pos() 是否与通过按钮的 blit 返回到主表面的坐标相匹配。

这与您的示例类似,虽然仍然有所不同。


2

在pygame(Python中)创建按钮的另一种好方法是安装名为pygame_widgets的包(pip3 install pygame_widgets)。

# Importing modules
import pygame as pg
import pygame_widgets as pw

# Creating screen
pg.init()
screen = pg.display.set_mode((800, 600))
running = True
button = pw.Button(
    screen, 100, 100, 300, 150, text='Hello',
    fontSize=50, margin=20,
    inactiveColour=(255, 0, 0),
    pressedColour=(0, 255, 0), radius=20,
    onClick=lambda: print('Click')
)

在运行时:

events = pg.event.get()
for event in events:
    if event.type == pg.QUIT:
        running = False
button.listen(events)
button.draw()
pg.display.update()

1
您在网上找到的“代码”不是很好。制作按钮所需的只有这个。将此放置在代码开头附近即可:
def Buttonify(Picture, coords, surface):
    image = pygame.image.load(Picture)
    imagerect = image.get_rect()
    imagerect.topright = coords
    surface.blit(image,imagerect)
    return (image,imagerect)

将以下内容放入游戏循环中。同时,在游戏循环的某个地方:
Image = Buttonify('YOUR_PICTURE.png',THE_COORDS_OF_THE_BUTTONS_TOP_RIGHT_CORNER, THE_NAME_OF_THE_SURFACE)

同时将以下内容放入游戏循环中,无论您在何处使用for event in pygame.event.get

if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
     mouse = pygame.mouse.get_pos
     if Image[1].collidepoint(mouse):
        #code if button is pressed goes here

所以,buttonify加载将显示在按钮上的图像。这个图像必须是一个.jpg文件或者任何其他与代码在同一目录中的图片文件。Picture是它的名称。名称必须有.jpg或其他后缀,并且名称必须用引号括起来。Buttonify中的coords参数是您屏幕或从pygame打开的窗口的右上角坐标。surface就是这个东西:
blahblahblah = pygame.surface.set_mode((WindowSize))
 /|\
  |
  Surface's Name

所以,该函数创建了一个名为“image”的Pygame表面,它在其周围放置了一个名为“imagerect”的矩形(用于设置其位置和在blitting时的第二个参数),然后设置其位置并在倒数第二行blits它。
下一段代码将“Image”作为“image”和“imagerect”的元组。
最后一段代码有if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:,这基本上意味着如果按下了左鼠标按钮。此代码必须在for event in pygame.event.get中。下一行使鼠标成为鼠标位置的元组。最后一行检查鼠标光标是否位于Image [1]的区域内,因为我们知道它是“imagerect”。代码遵循此规则。
如果需要进一步解释,请告诉我。

0

所以你需要创建一个名为button的函数,该函数接收8个参数。1)按钮消息 2)按钮左上角的X位置 3)按钮左上角的Y位置 4)按钮的宽度 5)按钮的高度 6)非活动颜色(背景颜色) 7)活动颜色(当你悬停时的颜色) 8)你想要执行的操作名称。

def button (msg, x, y, w, h, ic, ac, action=None ):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if (x+w > mouse[0] > x) and (y+h > mouse[1] > y):
        pygame.draw.rect(watercycle, CYAN, (x, y, w, h))
        if (click[0] == 1 and action != None):
            if  (action == "Start"):
                game_loop()
            elif  (action == "Load"):
                 ##Function that makes the loading of the saved file##
            elif  (action == "Exit"):
                pygame.quit()

    else:
        pygame.draw.rect(watercycle, BLUE, (x, y, w, h))
        smallText = pygame.font.Font("freesansbold.ttf", 20)
        textSurf, textRect = text_objects(msg, smallText)
        textRect.center = ( (x+(w/2)), (y+(h/2)) )
        watercycle.blit(textSurf, textRect)

因此,当您创建游戏循环并调用按钮函数时:

button("开始", 600, 120, 120, 25, 蓝色, 青色, "开始")


0

0

这是一个修改过的类的版本,原本是由其他人发布的,但在一个非常相似(但已关闭)的问题上对我有用。

class Button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.ogcol = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text

    def draw(self,win,outline=None):
        #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(win, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
            
        pygame.draw.rect(win, self.color, (self.x,self.y,self.width,self.height),0)
        
        if self.text != '':
            font = pygame.font.SysFont('Consolas', 24)
            text = font.render(self.text, 1, (0,0,0))
            win.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
        global STATE
        #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                self.color = (128,128,128)
            else:
                self.color = self.ogcol
        else:
            self.color = self.ogcol
        global ev
        for event in ev:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if pos[0] > self.x and pos[0] < self.x + self.width:
                    if pos[1] > self.y and pos[1] < self.y + self.height:
                        return True

变量ev将是事件列表(pygame.event.get())。 一些示例语法如下:
#class up here
btn = Button((255,0,0),100,100,200,50,text="print hi")
#do above before you start the loop
#all of the pygame init and loop
#Define screen as the window

btn.draw(screen)
if btn.isOver(pygame.mouse.get_pos()) == True:
    print("hi")
pygame.display.update()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接