当我将鼠标悬停在 pygame 中的按钮上时,如何弹出一个文本框

How do i make a text box pop up when i hover over a button in pygame

我希望能够在我将鼠标悬停在按钮上时弹出一个文本框,现在当我将鼠标悬停在按钮上时按钮会改变颜色但没有显示文本框我该如何实现或我需要到完全不同的东西,比如当我将鼠标悬停在任何一种方式上时弹出一个新屏幕悬停不起作用,我不知道如何修复它和 id 喜欢一些帮助

import pygame
pygame.init()
pygame.font.init()
colours = {"White" : (255, 255, 255), "Black" : (0, 0, 0), "Red" : (255, 0, 0), "Blue" : (0, 0, 255), "Green" : (0, 255, 0)}
orighpamt = 10
currentGoblin = 0

class Screen():
    def __init__(self, title, width=400, height=600, fill=colours["White"]):
        self.title=title
        self.width=width
        self.height = height
        self.fill = fill
        self.current = False

    def makeCurrent(self):
        pygame.display.set_caption(self.title)
        self.current = True
        self.screen = pygame.display.set_mode((self.width, self.height))

    def endCurrent(self):
        self.current = False

    def checkUpdate(self):
        return self.current
    def screenUpdate(self):
        if(self.current):
            self.screen.fill(self.fill)

    def returnTitle(self):
        return self.screen

class Button():
        def __init__(self, x, y, sx, sy, bcolour, fbcolour, font, fontsize, fcolour, text):
            self.x = x
            self.y = y
            self.sx = sx
            self.sy = sy
            self.bcolour = bcolour
            self.fbcolour = fbcolour
            self.fcolour = fcolour
            self.fontsize = fontsize
            self.text = text
            self.current = False
            self.buttonf = pygame.font.SysFont(font, fontsize)
        def showButton(self, display):
            if(self.current):
                pygame.draw.rect(display, self.fbcolour, (self.x, self.y, self.sx, self.sy))
            else:
                pygame.draw.rect(display, self.bcolour, (self.x, self.y, self.sx, self.sy))

            textsurface = self.buttonf.render(self.text, False, self.fcolour)
            display.blit(textsurface, ((self.x + (self.sx/2) - (self.fontsize/2)*(len(self.text)/2) - 5,(self.y + (self.sy/2) -(self.fontsize/2) - 4))))
        def focusCheck(self, mousepos, mouseclick):
            if(mousepos[0] >= self.x and mousepos[0] <= self.x + self.sx and mousepos[1] >= self.y and mousepos[1] <= self.y + self.sy):
                self.current = True
                return mouseclick
            else:
                self.current = False
                return False
class Enemy(pygame.sprite.Sprite):

    def __init__(self, dx, dy, filename):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load(filename).convert()

        self.rect = self.image.get_rect()
        self.rect.x = dx
        self.rect.y = dy



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



menuScreen = Screen("Menu Screen")
screen2 = Screen("Screen 2")

win = menuScreen.makeCurrent()


done = False
font = pygame.font.Font('freesansbold.ttf', 32)
clickdamage = 1
hitpoints = orighpamt
DungeonButton = Button(125, 500, 150, 50, colours["Black"], colours["Blue"], "arial", 20, colours["White"], "Dungeon")
hitboxButton = Button(80, 50, 280, 400, colours["White"], colours["Red"], "arial", 20, colours["White"], "")
hitpointamount = Button(100, 0, 200, 50, colours["White"], colours["Black"], "arial", 20, colours["Black"], str(hitpoints))
shopButton = Button(125, 500, 150, 50, colours["Black"], colours["Red"], "arial", 20, colours["White"], "Shop")
Assassin_Text = Button(50, 350, 400, 50, colours["White"], colours["Red"], "arial", 18, colours["Black"], "Sharpen your sword and increase your damage per click")
Assassin_Upgrade = Button(10, 300, 125, 50, colours["Black"], colours["Red"], "arial", 15, colours["White"], "Assassin")
goblin = Enemy(0 , 20, "images\goblin-resized.png")
goblin2 = Enemy(80 , 50, "images\monster2.png")
toggle = False
while not done:
    menuScreen.screenUpdate()
    screen2.screenUpdate()
    mouse_pos = pygame.mouse.get_pos()
    keys = pygame.key.get_pressed()

    mouse_click = False
    for event in pygame.event.get():
        if(event.type == pygame.QUIT):
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_click = True

    if menuScreen.checkUpdate():
        
        screen2button = shopButton.focusCheck(mouse_pos, mouse_click)
        shopButton.showButton(menuScreen.returnTitle())
        if screen2button:
            win = screen2.makeCurrent()
            
            menuScreen.endCurrent()    
    elif screen2.checkUpdate():
        returnm = DungeonButton.focusCheck(mouse_pos, mouse_click)
        Assassin_Upgrade.showButton(screen2.returnTitle())
        if Assassin_Upgrade.focusCheck(mouse_pos):
            Assassin_Text.showButton(screen2.returnTitle())
        if returnm:
            win = menuScreen.makeCurrent()
            screen2.endCurrent()

    pygame.display.update()

pygame.quit()

回答提供 Minimal, Reproducible Example 的问题更容易。您的示例具有外部图像和字体依赖项,需要克服这些依赖项才能让其他人调试您的代码。

如果您的按钮有关联的矩形,那么您可以使用 Rect.colliderect(position) 判断鼠标光标是否悬停在按钮上。

这是一个最小的示例,显示鼠标位于矩形中时的一些悬停文本:

import pygame
WIDTH = 640
HEIGHT = 480
FPS = 30

pygame.init()
pygame.font.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(f"Color: purple")
clock = pygame.time.Clock()

# create a centered rectangle to fill with color
color_rect = pygame.Rect(100, 100, WIDTH - 200, HEIGHT - 200)  

font = pygame.font.SysFont(None, 50, True)
msg = "  Hovering Message  "
hover_surface = font.render(msg, True, pygame.Color("chartreuse"), pygame.Color("firebrick"))

hovering = False
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    # update game elements - Get mouse position
    mx, my = pygame.mouse.get_pos()
    # draw surface - fill background
    screen.fill(pygame.Color("grey"))
    ## draw central rect
    screen.fill(pygame.Color("purple"), color_rect)
    ## display the hovering text if the mouse is over the rectangle
    if color_rect.collidepoint((mx, my)):
        screen.blit(hover_surface, (mx, my))
    # show surface
    pygame.display.update()
    # limit frames
    clock.tick(FPS)
pygame.quit()

您的代码使用了大量的原始几何计算,在长 运行 中使用一些本机 pygame 元素可能更容易。例如,您可以将您的按钮设为不可移动的 Sprites,并将它们放在一个 Sprite 组中,以便于管理它们。

为您的 class 添加另一个文本属性。例如:

class Button():
    def __init__(self, x, y, sx, sy, bcolour, fbcolour, font, fontsize, fcolour, text, tiptext):
        # [...]

        self.tiptextsurface = self.buttonf.render(tiptext, False, (0, 0, 0), (255, 255, 0))

Button.showTip 方法中绘制文本,当设置 self.current 时:

class Button():
    # [...]

    def showTip(self, display):
        if self.current:
            mouse_pos = pygame.mouse.get_pos()
            display.blit(self.tiptextsurface, (mouse_pos[0]+16, mouse_pos[1]))


基于您的代码的最小示例:

我已经简化了 Button class,但它的行为与您问题中的 class 完全一样。

import pygame
pygame.init()

class Button():
    def __init__(self, x, y, sx, sy, bcolour, fbcolour, font, fontsize, fcolour, text, tiptext):
        self.rect = pygame.Rect(x, y, sx, sy)
        self.bcolour = bcolour
        self.fbcolour = fbcolour
        self.fcolour = fcolour
        self.fontsize = fontsize
        self.current = False
        self.buttonf = pygame.font.SysFont(font, fontsize)
        self.textsurface = self.buttonf.render(text, False, self.fcolour)
        self.tiptextsurface = self.buttonf.render(tiptext, False, (0, 0, 0), (255, 255, 0))
        
    def showButton(self, display):
        color = self.fbcolour if self.current else self.bcolour
        pygame.draw.rect(display, color, self.rect)
        display.blit(self.textsurface, self.textsurface.get_rect(center = self.rect.center))

    def showTip(self, display):
        if self.current:
            mouse_pos = pygame.mouse.get_pos()
            display.blit(self.tiptextsurface, (mouse_pos[0]+16, mouse_pos[1]))

    def focusCheck(self, mousepos, mouseclick):
        self.current = self.rect.collidepoint(mousepos)
        return mouseclick if self.current else True
                
screen = pygame.display.set_mode((400, 600))
clock = pygame.time.Clock()
font = pygame.font.Font('freesansbold.ttf', 32)
shopButton = Button(125, 500, 150, 50, "black", "red", "arial", 20, "white", "Shop", "Enter the shop")

done = False
while not done:    
    clock.tick(60)
    for event in pygame.event.get():
        if(event.type == pygame.QUIT):
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_click = True

    mouse_pos = pygame.mouse.get_pos()
    mouse_click = False
    screen2button = shopButton.focusCheck(mouse_pos, mouse_click)

    screen.fill((255, 255, 255))
    shopButton.showButton(screen)
    shopButton.showTip(screen)
    pygame.display.update()

pygame.quit()