当我将鼠标悬停在pygame上时,为什么按钮不改变颜色? [英] Why won't my button change color when i hover over it pygame?

查看:146
本文介绍了当我将鼠标悬停在pygame上时,为什么按钮不改变颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是pygame的新手,一直在尝试使用一些按钮创建一个简单的界面。当鼠标悬停在按钮上时,我无法更改按钮的颜色。

I'm new to pygame and have been attempting to create a simple interface with some buttons. I can't get the button to change color when the mouse hovers over it.

我设法创建了按钮,但无法使其与鼠标交互。
代码创建一个带有绿色按钮实例的按钮对象。
鼠标悬停时,应将按钮从绿色更改为红色。

I've managed to create the button, but cannot get it to interact with my mouse. The code create an button object with one instance of a green button. It should change the button from green to red when mouse hovers over.

import pygame

pygame.init()

display_width = 1200
display_height = 600

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)

StartScreen = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Log In')
clock = pygame.time.Clock()

StartScreen.fill(white)

class Buttons():
    def __init__(self, color, x, y, width, height, text=''):
        self.color = color
        self.x = int(x)
        self.y = int(y)
        self.w = int(width)
        self.h = int(height)
        self.text = text


    def Draw(self, StartScreen, outline=None):
        if outline:
            pygame.draw.rect(StartScreen, outline, (float(self.x-2), float(self.y-2), float(self.w+4), float(self.h+4)), 0)

        pygame.draw.rect(StartScreen, self.color, (self.x, self.y, self.w, self.h), 0)

        if self.text != '':
            font = pygame.font.SysFont('comicsans', 20)
            text = font.render(self.text, 1, black)
            StartScreen.blit(text, (self.x + (self.w/2 - text.get_width()/2), self.y + (self.h/2 - text.get_height()/2)))


    def MouseOver(self, pos):
        if pos[0] > self.x and pos[0] < self.x + self.w:
            if pos[1] > self.y and pos[1] < self.y + self.h:
                return True

        return False

def redrawWindow():
    StartScreen.fill(white)
    GrnBut.Draw(StartScreen, black)

run = True

GrnBut = Buttons(green, 150, 200, 90, 100, 'Press')
while run:
    redrawWindow()
    pygame.display.update()

    for event in pygame.event.get():
        pos = pygame.mouse.get_pos()

        Exit = False
        while not Exit:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    print(event)
                    pygame.quit()
                    quit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            if GrnBut.MouseOver(pos):
                print("Clicked")

        if event.type == pygame.MOUSEMOTION:
            if GrnBut.MouseOver(pos):
                GrnBut.color = red
            else:
                GrnBut.color = green



推荐答案

您的主要问题是您的事件循环中有一个嵌套的事件循环:

Your main problem is that you have a nested event loop inside your event loop:

while run:         # outer loop
    redrawWindow()
    pygame.display.update()

    for event in pygame.event.get():
        pos = pygame.mouse.get_pos()

        Exit = False
        while not Exit:       # inner loop
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    print(event)
                    pygame.quit()
                    quit()

当执行到达此内部循环时, redrawWindow() GrnBut.MouseOver(pos)

When execution reaches this inner loop, neither redrawWindow() or GrnBut.MouseOver(pos) is ever called again.

只需摆脱它:

while run:
    redrawWindow()
    pygame.display.update()

    for event in pygame.event.get():
        pos = pygame.mouse.get_pos()

        if event.type == pygame.QUIT:
            print(event)
            pygame.quit()
            quit()






可以使用pygame的某些功能来改进您的代码,例如 Sprite Rect 类。

这里是一个示例,说明如何创建 Button的更多 pygamy版本类支持多个不同的按钮:

Here's an example of how you could create a more "pygamy" version of your Button class that supports multiple, different buttons:

import pygame

pygame.init()

display_width = 1200
display_height = 600

# use python style variable names (lowercase)
screen = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Log In')
clock = pygame.time.Clock()

# load the font only once instead of every frame
font = pygame.font.SysFont('comicsans', 20)

# class name should be singular
class Button(pygame.sprite.Sprite):
    # 1) no need to have 4 parameters for position and size, use pygame.Rect instead
    # 2) let the Button itself handle which color it is
    # 3) give a callback function to the button so it can handle the click itself 
    def __init__(self, color, color_hover, rect, callback, text='', outline=None):
        super().__init__()
        self.text = text
        # a temporary Rect to store the size of the button
        tmp_rect = pygame.Rect(0, 0, *rect.size)

        # create two Surfaces here, one the normal state, and one for the hovering state
        # we create the Surfaces here once, so we can simple blit them and dont have
        # to render the text and outline again every frame
        self.org = self._create_image(color, outline, text, tmp_rect)
        self.hov = self._create_image(color_hover, outline, text, tmp_rect)

        # in Sprites, the image attribute holds the Surface to be displayed...
        self.image = self.org
        # ...and the rect holds the Rect that defines it position
        self.rect = rect
        self.callback = callback

    def _create_image(self, color, outline, text, rect):
        # function to create the actual surface
        # see how we can make use of Rect's virtual attributes like 'size'
        img = pygame.Surface(rect.size)
        if outline:
            # here we can make good use of Rect's functions again
            # first, fill the Surface in the outline color
            # then fill a rectangular area in the actual color
            # 'inflate' is used to 'shrink' the rect
            img.fill(outline)
            img.fill(color, rect.inflate(-4, -4))
        else:
            img.fill(color)

        # render the text once here instead of every frame
        if text != '':
            text_surf = font.render(text, 1, pygame.Color('black'))
            # again, see how easy it is to center stuff using Rect's attributes like 'center'
            text_rect = text_surf.get_rect(center=rect.center)
            img.blit(text_surf, text_rect)
        return img

    def update(self, events):
        # here we handle all the logic of the Button
        pos = pygame.mouse.get_pos()
        hit = self.rect.collidepoint(pos)
        # if the mouse in inside the Rect (again, see how the Rect class
        # does all the calculation for use), use the 'hov' image instead of 'org'
        self.image = self.hov if hit else self.org
        for event in events:
            # the Button checks for events itself.
            # if this Button is clicked, it runs the callback function
            if event.type == pygame.MOUSEBUTTONDOWN and hit:
                self.callback(self)

run = True

# we store all Sprites in a Group, so we can easily
# call the 'update' and 'draw' functions of the Buttons
# in the main loop
sprites = pygame.sprite.Group()
sprites.add(Button(pygame.Color('green'), 
                   pygame.Color('red'), 
                   pygame.Rect(150, 200, 90, 100), 
                   lambda b: print(f"Button '{b.text}' was clicked"),
                   'Press',
                   pygame.Color('black')))

sprites.add(Button(pygame.Color('dodgerblue'), 
                   pygame.Color('lightgreen'), 
                   pygame.Rect(300, 200, 90, 100), 
                   lambda b: print(f"Click me again!"),
                   'Another'))

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

    # update all sprites
    # it now doesn't matter if we have one or 200 Buttons
    sprites.update(events)
    # clear the screen
    screen.fill(pygame.Color('white'))
    # draw all sprites/Buttons
    sprites.draw(screen)
    pygame.display.update()
    # limit framerate to 60 FPS
    clock.tick(60)

这篇关于当我将鼠标悬停在pygame上时,为什么按钮不改变颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆