在PyGame中创建按钮

如何解决在PyGame中创建按钮

我正在制作一个用于自动时间表的程序,我设法创建了一个标题,但是我想添加一个登录页面注册一个进入新页面的按钮。我还想在这些新页面添加一个返回按钮。我当时正在使用programmingpixels.com来提供帮助,但是我仍然无法做我想做的事。我是使用PyGame的新手,所以我可能没有完成高效的代码,可能会出现很多错误。我的标题屏幕以前可以正常工作,但是当我尝试添加这些按钮时,它是空白的,不会让我退出屏幕。任何帮助都会很棒。谢谢。

import pygame

import pygame.freetype

from pygame.sprite import Sprite

from pygame.rect import Rect

from enum import Enum

PINK = (250,100,100)

WHITE = (255,255,255)

BLACK = (0,0)

def create_surface_with_text(text,font_size,text_rgb,bg_rgb):

    font = pygame.freetype.SysFont("Arial",bold=True)

    surface,_ = font.render(text=text,fgcolor=text_rgb,bgcolor=bg_rgb)

    return surface.convert_alpha()


class UIElement(Sprite):
   
    def __init__(self,center_position,text,bg_rgb,action=None):
     
        self.mouse_over = False  

        # what happens when the mouse is not over the element
        default_image = create_surface_with_text(
            text=text,font_size=font_size,text_rgb=text_rgb,bg_rgb=bg_rgb
        )

        # what happens when the mouse is over the element
        highlighted_image = create_surface_with_text(
            text=text,font_size=font_size * 1.1,bg_rgb=bg_rgb
        )

        self.images = [default_image,highlighted_image]

        self.rects = [
            default_image.get_rect(center=center_position),highlighted_image.get_rect(center=center_position),]

        self.action = action
        
        super().__init__()

    @property
    def image(self):
        return self.images[1] if self.mouse_over else self.images[0]

    @property
    def rect(self):
        return self.rects[1] if self.mouse_over else self.rects[0]

    def update(self,mouse_pos,mouse_up):
        if self.rect.collidepoint(mouse_pos):
            self.mouse_over = True
        else:
            self.mouse_over = False

    def draw(self,surface):
        surface.blit(self.image,self.rect)


def main():
    pygame.init()

    screen = pygame.display.set_mode((800,600))
    game_state = GameState.LOGIN

    while True:
        if game_state == GameState.LOGIN:
            game_state = log_in(screen)

        if game_state == GameState.SIGNUP:
            game_state = sign_up(screen)

        if game_state == GameState.RETURN:
            game_state = title_screen(screen)

        if game_state == GameState.QUIT:
            pygame.quit()
            return

def title_screen(screen):

    login_btn = UIElement(

        center_position=(400,300),font_size=30,bg_rgb=WHITE,text_rgb=BLACK,text="Log In",action=GameState.LOGIN,)

    signup_btn = UIElement(
        center_position=(400,200),)

    uielement = UIElement(
        center_position=(400,100),font_size=40,bg_rgb=PINK,text="Welcome to the Automated TiMetable Program",action=GameState.QUIT,)

    buttons = [login_btn,signup_btn]

    while True:
        mouse_up = False
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                mouse_up = True
            elif event.type == pygame.QUIT:
                pygame.quit()
                sys.exitIO
        screen.fill(PINK)

        for button in buttons:
            ui_action = button.update(pygame.mouse.get_pos(),mouse_up)
            if ui_action is not None:
                return ui_action
            button.draw(screen)

        pygame.display.flip()

def log_in(screen):

    return_btn = UIElement(

        center_position=(140,570),font_size=20,text="Return to main menu",action=GameState.TITLE,)

    while True:
        mouse_up = False
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                mouse_up = True
        screen.fill(PINK)

        ui_action = return_btn.update(pygame.mouse.get_pos(),mouse_up)
        if ui_action is not None:
            return ui_action
        return_btn.draw(screen)

        pygame.display.flip()

class GameState(Enum):

    LOGIN = -1

    SIGNUP = 0

    RETURN = 1

    QUIT = 2


if __name__ == "__main__":

    main() 

解决方法

对于初学者,GameState缺少TITLE值。

class GameState(Enum):
    # ...
    TITLE = 3

添加此代码可使代码运行。

log_in()函数无法处理正在关闭的窗口。在每个事件循环中,您必须处理pygame.QUIT事件。例如:

def log_in( screen ):
    # ...

    while True:
        mouse_up = False
        for event in pygame.event.get():
            if ( event.type == pygame.QUIT ):
                pygame.event.post( pygame.event.Event( pygame.QUIT ) )    # re-send the quit event to the next loop
                return GameState.QUIT
            elif ( event.type == pygame.MOUSEBUTTONUP and event.button == 1 ):
                mouse_up = True    # Mouse button 1 weas released

        ui_action = return_btn.update( pygame.mouse.get_pos(),mouse_up )
        if ui_action is not None:
            print( "log_in() - returning action" )
            return ui_action

        screen.fill(PINK)
        return_btn.draw(screen)
        pygame.display.flip()

当在控件上释放鼠标按钮时,UIElement.update()看起来应该返回self.action。但是,在现有代码中,什么也不会返回。可能需要这样:

class UIElement( Sprite ):
    # ...
    def update(self,mouse_pos,mouse_up):
        """ Track the mouse,setting the self.mouse_over.  Also check 
            if the mouse-button was clicked while over this control
            returning the pre-defined self.action,if so.     """

        result = None                    # No click => no action
        if self.rect.collidepoint(mouse_pos):
            self.mouse_over = True
            if ( mouse_up ):
                result = self.action     # Mouse was clicked on element,add action
        else:
            self.mouse_over = False
        return result

这些更改之后,您的脚本运行正常,然后在单击按钮时进入外部循环。外循环也不能正确处理退出,但可能只是同一组更改而已。

最好只有一个用户输入处理循环。具有这些单独的事件循环会在多个位置导致相同的问题。找出一种具有单个事件处理功能的方法,然后修改您的UI代码以使用它。这将使您的代码更容易编写和调试。

参考:所有代码

import pygame

import pygame.freetype

from pygame.sprite import Sprite

from pygame.rect import Rect

from enum import Enum

PINK = (250,100,100)

WHITE = (255,255,255)

BLACK = (0,0)

def create_surface_with_text(text,font_size,text_rgb,bg_rgb):

    font = pygame.freetype.SysFont("Arial",bold=True)

    surface,_ = font.render(text=text,fgcolor=text_rgb,bgcolor=bg_rgb)

    return surface.convert_alpha()


class UIElement(Sprite):
   
    def __init__(self,center_position,text,bg_rgb,action=None):
     
        self.mouse_over = False  

        # what happens when the mouse is not over the element
        default_image = create_surface_with_text(
            text=text,font_size=font_size,text_rgb=text_rgb,bg_rgb=bg_rgb
        )

        # what happens when the mouse is over the element
        highlighted_image = create_surface_with_text(
            text=text,font_size=font_size * 1.1,bg_rgb=bg_rgb
        )

        self.images = [default_image,highlighted_image]

        self.rects = [
            default_image.get_rect(center=center_position),highlighted_image.get_rect(center=center_position),]

        self.action = action
        
        super().__init__()

    @property
    def image(self):
        return self.images[1] if self.mouse_over else self.images[0]

    @property
    def rect(self):
        return self.rects[1] if self.mouse_over else self.rects[0]

    def update(self,add action
        else:
            self.mouse_over = False
        return result


    def draw(self,surface):
        surface.blit(self.image,self.rect)


def main():
    pygame.init()

    screen = pygame.display.set_mode((800,600))
    game_state = GameState.LOGIN

    while True:
        if game_state == GameState.LOGIN:
            game_state = log_in(screen)

        if game_state == GameState.SIGNUP:
            game_state = sign_up(screen)

        if game_state == GameState.RETURN:
            game_state = title_screen(screen)

        if game_state == GameState.QUIT:
            pygame.quit()
            return

def title_screen(screen):

    login_btn = UIElement(
        center_position=(400,300),font_size=30,bg_rgb=WHITE,text_rgb=BLACK,text="Log In",action=GameState.LOGIN,)

    signup_btn = UIElement(
        center_position=(400,200),)

    uielement = UIElement(
        center_position=(400,100),font_size=40,bg_rgb=PINK,text="Welcome to the Automated Timetable Program",action=GameState.QUIT,)

    buttons = [login_btn,signup_btn]

    while True:
        mouse_up = False
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                mouse_up = True
            elif event.type == pygame.QUIT:
                pygame.quit()
                sys.exitIO
        screen.fill(PINK)

        for button in buttons:
            ui_action = button.update(pygame.mouse.get_pos(),mouse_up)
            if ui_action is not None:
                return ui_action
            button.draw(screen)

        pygame.display.flip()

def log_in(screen):

    return_btn = UIElement(
        center_position=(140,570),font_size=20,text="Return to main menu",action=GameState.TITLE,)

    while True:
        mouse_up = False
        for event in pygame.event.get():
            if ( event.type == pygame.QUIT ):
                pygame.event.post( pygame.event.Event( pygame.QUIT ) )    # re-send the quit event to the next loop
                return GameState.QUIT
            elif ( event.type == pygame.MOUSEBUTTONUP and event.button == 1 ):
                mouse_up = True    # Mouse button 1 weas released

        ui_action = return_btn.update( pygame.mouse.get_pos(),mouse_up )
        if ui_action is not None:
            print( "log_in() - returning action" )
            return ui_action

        screen.fill(PINK)
        return_btn.draw(screen)
        pygame.display.flip()



class GameState(Enum):

    LOGIN = -1
    SIGNUP = 0
    RETURN = 1
    QUIT = 2
    TITLE=3


if __name__ == "__main__":

    main() 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?