在pygame中按下编码按钮时更改屏幕上的文本和按钮上的文本

时间:2020-06-28 16:58:21

标签: python pygame

请有人为我提供有关如何更改代码的建议,以使屏幕文本和编码按钮文本一直保留到下一次单击鼠标按钮时为止,并且在释放鼠标按钮后不会消失。 现在,当我单击并按住鼠标按钮时,屏幕文本正在更改,但是编码按钮未更新。而且,在我释放鼠标按钮之后,文本又回到了初始状态。 我需要文本(在屏幕上和在按钮上)都可以更改,并且可以永远在屏幕上保持更新,或者直到再次单击鼠标按钮为止。 我制作了一个函数来在屏幕上绘制文本,并创建了一个在屏幕上绘制按钮的类。他们都工作。也许问题出在带有“ if”语句的主要逻辑中?

pygame.init()

# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

bgcolor = (54, 54, 54)

# defining the function to draw text on the screen
def draw_text(surface, text, pos):
    text_color = (255, 255, 255)
    text_font = pygame.font.SysFont('Times New Roman', 24)
    x, y = pos

    word_surface = text_font.render(text, 1, text_color)
    surface.blit(word_surface, (x, y))


# defining a class for buttons
class DrawButton():
    def __init__(self, button_text, button_x, button_y):
        self.button_text = button_text
        self.button_x = button_x
        self.button_y = button_y
        self.button_color_passive = (89, 89, 89)
        self.button_color_active = (212, 200, 235)
        self.button_width = 400
        self.button_height = 100
        self.cur = pygame.mouse.get_pos()
        self.click = pygame.mouse.get_pressed()

    def text_to_button(self): # defining the method for drawing a text on buttons
        bf_passive = pygame.font.SysFont('Times New Roman', 24)
        bf_passive_rend = bf_passive.render(self.button_text, 1, self.button_color_active)
        bf_passive_rect = bf_passive_rend.get_rect()

        bf_active = pygame.font.SysFont('Times New Roman', 28)
        bf_active_rend = bf_active.render(self.button_text, 1, self.button_color_passive)
        bf_active_rect = bf_active_rend.get_rect()

        if self.button_x + self.button_width > self.cur[0] > self.button_x \
                and self.button_y + self.button_height > self.cur[1] > self.button_y:
            bf_active_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
            screen.blit(bf_active_rend, bf_active_rect)
        else:
            bf_passive_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
            screen.blit(bf_passive_rend, bf_passive_rect)


    def draw_button(self): # defining the method for drawing button rectangle
        if self.button_x + self.button_width > self.cur[0] > self.button_x \
                and self.button_y + self.button_height > self.cur[1] > self.button_y:
           pygame.draw.rect(screen, self.button_color_passive, (self.button_x + 5, self.button_y + 5, self.button_width, self.button_height))
           pygame.draw.rect(screen, self.button_color_active, (self.button_x, self.button_y, self.button_width, self.button_height))
           if self.click[0] == 1:
               pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
        else:
           pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))


text1 = "Text 1"

text2 = "Text 2"

while True:

    dt = clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()

    screen.fill(bgcolor)

    text = text1

    if text == text1:
        button1 = DrawButton('Next', WIDTH - 435, HEIGHT - 150)
        button1.draw_button()
        button1.text_to_button()

    if text == text1 and button1.click[0] == 1:
        text = text2
        button2 = DrawButton('Next again', WIDTH - 435, HEIGHT - 150)
        button2.draw_button()
        button2.text_to_button()

    draw_text(screen, text, (40, 20))


    pygame.display.update()```

1 个答案:

答案 0 :(得分:0)

您应在循环之前而不是在内部使用text = text1。然后保留新文本。

但是更大的问题是

button1.click[0] == 1

在按下按钮时始终为True,因此在将文本从第一更改为第二以及随后从第二更改为第一时会出现问题,因为在按住按钮的同时会一次又一次地更改文本-最后,当您释放鼠标键时,您可以获得相同的文本(或者您可以看到文本一直在变化)。

您应该使用事件MOUSEBUTTONDOWN,该事件仅在创建一次时-当您开始按下时才创建-但在按下时不会创建。

text1 = "Text 1"
text2 = "Text 2"

text = text1

while True:

    dt = clock.tick(FPS)

    # --- events (without draws) ---
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            if text == text1:
                text = text2
            else:
                text = text1
                
    # --- changes (without draws) ---

    if text == text1:
        button = DrawButton('Next', WIDTH-435, HEIGHT-150)
    else:
        button = DrawButton('Next again', WIDTH-435, HEIGHT-150)

    # --- draws (without changes) ---

    screen.fill(bgcolor)

    button.draw_button()
    button.text_to_button()
        
    draw_text(screen, text, (40, 20))

    pygame.display.update()

完整的工作代码:

import pygame

# --- constants ---

# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30

# --- classes ---

# defining a class for buttons
class DrawButton():
    
    def __init__(self, button_text, button_x, button_y):
        self.button_text = button_text
        self.button_x = button_x
        self.button_y = button_y
        self.button_color_passive = (89, 89, 89)
        self.button_color_active = (212, 200, 235)
        self.button_width = 400
        self.button_height = 100
        self.cur = pygame.mouse.get_pos()
        self.click = pygame.mouse.get_pressed()

    def text_to_button(self): # defining the method for drawing a text on buttons
        bf_passive = pygame.font.SysFont('Times New Roman', 24)
        bf_passive_rend = bf_passive.render(self.button_text, 1, self.button_color_active)
        bf_passive_rect = bf_passive_rend.get_rect()

        bf_active = pygame.font.SysFont('Times New Roman', 28)
        bf_active_rend = bf_active.render(self.button_text, 1, self.button_color_passive)
        bf_active_rect = bf_active_rend.get_rect()

        if self.button_x + self.button_width > self.cur[0] > self.button_x \
                and self.button_y + self.button_height > self.cur[1] > self.button_y:
            bf_active_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
            screen.blit(bf_active_rend, bf_active_rect)
        else:
            bf_passive_rect.center = (int(self.button_x + (self.button_width / 2)), int(self.button_y + (self.button_height / 2)))
            screen.blit(bf_passive_rend, bf_passive_rect)


    def draw_button(self): # defining the method for drawing button rectangle
        if self.button_x + self.button_width > self.cur[0] > self.button_x \
                and self.button_y + self.button_height > self.cur[1] > self.button_y:
           pygame.draw.rect(screen, self.button_color_passive, (self.button_x + 5, self.button_y + 5, self.button_width, self.button_height))
           pygame.draw.rect(screen, self.button_color_active, (self.button_x, self.button_y, self.button_width, self.button_height))
           if self.click[0] == 1:
               pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))
        else:
           pygame.draw.rect(screen, self.button_color_passive, (self.button_x, self.button_y, self.button_width, self.button_height))

# --- functions ---

# defining the function to draw text on the screen
def draw_text(surface, text, pos):
    text_color = (255, 255, 255)
    text_font = pygame.font.SysFont('Times New Roman', 24)
    x, y = pos

    word_surface = text_font.render(text, 1, text_color)
    surface.blit(word_surface, (x, y))

# --- main ---

pygame.init()

screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

bgcolor = (54, 54, 54)

text1 = "Text 1"
text2 = "Text 2"

text = text1

while True:

    dt = clock.tick(FPS)

    # --- events (without draws) ---
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            if text == text1:
                text = text2
            else:
                text = text1
                
    # --- changes (without draws) ---

    if text == text1:
        button = DrawButton('Next', WIDTH-435, HEIGHT-150)
    else:
        button = DrawButton('Next again', WIDTH-435, HEIGHT-150)

    # --- draws (without changes) ---

    screen.fill(bgcolor)

    button.draw_button()
    button.text_to_button()
        
    draw_text(screen, text, (40, 20))

    pygame.display.update()

顺便说一句:

您可以进行许多其他更改-即。使用pygame.Rect保持按钮的大小和位置,然后检查rect.collidepoint(mouse.pos)来检测鼠标是否在按钮上方。并使用它显示blit(screen, image, rect)或将文本居中放置在rect-text_rect = text_image.get_rect(center=button_rect.center)等上。

我所有的更改

import pygame

# --- constants ---

# setting the window size and FPS
SIZE = WIDTH, HEIGHT = (640, 640)
FPS = 30

# --- classes ---

# defining a class for buttons

class DrawButton():
    
    def __init__(self, text, x, y, function=None):
        '''Init all needed variables only once'''

        self.rect = pygame.Rect(x, y, 400, 100)
        self.text = text
        self.function = function
        
        self.shadow_rect = self.rect.copy()
        self.shadow_rect.x += 5
        self.shadow_rect.y += 5

        self.color_passive = (89, 89, 89)
        self.color_active = (212, 200, 235)
        self.color_click = (0, 200, 0)

        self.hovered = False
        self.clicked = False

        self.font_passive = pygame.font.SysFont('Times New Roman', 24)
        self.font_active = pygame.font.SysFont('Times New Roman', 28)
        
        self.render_text()
        
    def render_text(self):
        '''Render text but don't display it'''
        
        self.passive_text = self.font_passive.render(self.text, 1, self.color_active)
        self.passive_rect = self.passive_text.get_rect(center=self.rect.center)

        self.active_text = self.font_active.render(self.text, 1, self.color_passive)
        self.active_rect = self.active_text.get_rect(center=self.rect.center)

    def handle_event(self, event):
        '''Check all events and change variables - without drawing and rendering'''
        
        if event.type == pygame.MOUSEMOTION:
            self.hovered = self.rect.collidepoint(event.pos)
            
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.hovered:
                self.clicked = True
                #if self.function:
                #    self.function()
                    
        if event.type == pygame.MOUSEBUTTONUP:
            if self.hovered:
                self.clicked = False
                # run function when button is released
                if self.function:
                    self.function()
        
    def draw(self, screen):
        '''Draw rectangle and text but don't render text'''
        
        if self.hovered:
            # shadow
            pygame.draw.rect(screen, self.color_passive, self.shadow_rect)
            # rect
            if self.clicked:
                pygame.draw.rect(screen, self.color_click, self.rect)
            else:
                pygame.draw.rect(screen, self.color_active, self.rect)
            # text
            screen.blit(self.active_text, self.active_rect)
        else:
            # rect
            pygame.draw.rect(screen, self.color_passive, self.rect)
            # text
            screen.blit(self.passive_text, self.passive_rect)

# --- functions ---

# defining the function to draw text on the screen
def draw_text(surface, text, pos):
    color = (255, 255, 255)
    
    font = pygame.font.SysFont('Times New Roman', 24)
    image = font.render(text, 1, color)
    
    surface.blit(image, pos)

def on_click_1():
    global text
    
    if text == text1:
        text = text2
        button1.text = 'Next again'
        button1.render_text()
    else:
        text = text1
        button1.text = 'Next'
        button1.render_text()

def on_click_2():
    global text
    
    if text == "Hello":
        text = "World"
    else:
        text = "Hello"

# --- main ---

pygame.init()

screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

bgcolor = (54, 54, 54)

text1 = "Text 1"
text2 = "Text 2"

text = text1

# create button only once and assign function which it has to execute when it is pressed
button1 = DrawButton('Next', WIDTH-435, HEIGHT-150, on_click_1)
button2 = DrawButton('Press', WIDTH-435, HEIGHT-350, on_click_2)

while True:

    dt = clock.tick(FPS)

    # --- events ---
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        button1.handle_event(event)
        button2.handle_event(event)
        
    # --- changes (without draws) ---

    # empty
    
    # --- draws (without changes) ---
    
    screen.fill(bgcolor)
    
    button1.draw(screen)
    button2.draw(screen)
    
    draw_text(screen, text, (40, 20))

    pygame.display.update()