python - 文本大小变化持久性

标签 python pygame

我将从简单地复制并粘贴我的大量代码开始:

# Libraries #

import pygame
from pygame.locals import *
import ResolutionMenu

# Classes #

class GuiSettings:
    def __init__(self):
        self.TextSize = 20
        self.button_color = (35, 65, 145)
        self.button_color_hover = (70, 105, 150)

class Button():
    def __init__(self, x, y, width, height, outline, settings, text = "", action = None):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.settings = settings
        self.action = action
        self.outline = outline

    def draw(self, screen, outline = None):

        if self.outline:
            pygame.draw.rect(screen, self.outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)


        color = self.settings.button_color if not self.isOver(pygame.mouse.get_pos()) else self.settings.button_color_hover
        pygame.draw.rect(screen, color, (self.x, self.y, self.width, self.height), 0)

        if self.text != "":
            font = pygame.font.SysFont('segoeuisemibold', self.settings.TextSize)
            text = font.render(self.text, 1, (0, 0, 0))
            screen.blit(text, (self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))

    def update(self, events):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN and self.isOver(pygame.mouse.get_pos()) and self.action:
                self.action()

    def isOver(self, pos):
        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         
        return False


# Variables # 

settings = GuiSettings()
Click = False
Clock = pygame.time.Clock()
H, W = ResolutionMenu.resolution
pygame.init()
pygame.display.set_caption("Main Menu")
font = pygame.font.SysFont(None, settings.TextSize)
screen = pygame.display.set_mode((ResolutionMenu.resolution))

# Functions #


def draw_text_center(text, font, colour, surface):
        textobj = font.render(text, 1, colour)
        textrect = textobj.get_rect()
        textrect.center = ((H / 2), (W / 10))
        surface.blit(textobj, textrect)

def draw_text(text, font, colour, surface, XandY):
        textobj = font.render(text, 1, colour)
        textrect = textobj.get_rect()
        textrect.topleft = (XandY)
        surface.blit(textobj, textrect)

def MainMenu():
    while True:
        if ResolutionMenu.resolution == (800, 600):

            screen.fill ((0, 0, 0))

            draw_text_center("Main Menu Navigation", font, (255, 255, 255), screen)

            mx, my = pygame.mouse.get_pos()
            button1 = pygame.Rect((W/10), (H/5), (W/3), (H/15))
            button2 = pygame.Rect((W/10), (H/2), (W/3), (H/15))

            if button1.collidepoint((mx, my)):
                if Click:
                    game()
                
            if button2.collidepoint((mx, my)):
                if Click:
                    OptionsMenu()

            pygame.draw.rect(screen, (255, 0, 0), button1)
            pygame.draw.rect(screen, (255, 0, 0,), button2)
            
            Click = False        
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        pygame.quit()
                
                if event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        Click = True

            pygame.display.update()
            Clock.tick(60)
        
def game():
    running = True
    while running:
        screen.fill((0,0,0))
        
        draw_text('Test 1', font, (255, 255, 255), screen, (20, 20))
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False
        
        pygame.display.update()
        Clock.tick(60)


def OptionsMenu():    

    screen = pygame.display.set_mode((800, 600))
    settings = GuiSettings()

    buttons = [
        Button(100, 150, 200, 50, (0, 0, 0), settings, "Set Text Size: 14", lambda: settings.__setattr__('TextSize', 14)),
        Button(500, 150, 200, 50, (0, 0, 0), settings, "Set Text Size: 16", lambda: settings.__setattr__('TextSize', 16)),
        Button(100, 300, 200, 50, (0, 0, 0), settings, "Set Text Size: 18", lambda: settings.__setattr__('TextSize', 18)),
        Button(500, 300, 200, 50, (0, 0, 0), settings, "Set Text Size: 20", lambda: settings.__setattr__('TextSize', 20))
    ]

    running = True
    while running:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                return
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    running = False

        for button in buttons:
            button.update(events)

        screen.fill((100, 100, 100))

        for button in buttons:
            button.draw(screen)
        

        pygame.display.flip()

MainMenu()

正如你所看到的,最近我一直在尝试为游戏制作一个主菜单导航面板,到目前为止一切进展顺利。然而,我遇到了一个问题。

问题是这样的:我创建了一个类,其中保存文本大小、按钮颜色和按钮悬停颜色的设置(当鼠标位置位于按钮区域内时,按钮的颜色将会改变)。

class GuiSettings:
    def __init__(self):
        self.TextSize = 20
        self.button_color = (35, 65, 145)
        self.button_color_hover = (70, 105, 150)

当我在 OptionMenu() 函数内部时,这完全可以正常工作,但是当通过按 esc 并返回到 MainMenu() 函数来中断该函数时,“主菜单导航”文本的文本大小 (<尽管使用“settings.TextSize”作为大小变量,但下面的代码)并没有改变。我不确定为什么会出现这种情况,因为选项菜单上使用 lambda 函数来更改文本大小的值。

buttons = [
        Button(100, 150, 200, 50, (0, 0, 0), settings, "Set Text Size: 14", lambda: settings.__setattr__('TextSize', 14)),
        Button(500, 150, 200, 50, (0, 0, 0), settings, "Set Text Size: 16", lambda: settings.__setattr__('TextSize', 16)),
        Button(100, 300, 200, 50, (0, 0, 0), settings, "Set Text Size: 18", lambda: settings.__setattr__('TextSize', 18)),
        Button(500, 300, 200, 50, (0, 0, 0), settings, "Set Text Size: 20", lambda: settings.__setattr__('TextSize', 20))
    ]

抱歉,这是一个很长的问题,感谢您的阅读,我希望比我更擅长这方面的人可以给我一些帮助。

最佳答案

您可以在主应用程序循环之前使用字体大小 settings.TextSize 创建字体对象。当您随后更改 settings.TextSize 时,此 font 对象不会神奇地发生变化。字体大小用于光栅化字体中的字形。离开OptionsMenu函数后,您需要创建一个具有新大小的新字体对象。
此外,您需要使用 global statement ,因为 fontsettings 是全局命名空间中的变量。

def MainMenu():
    global font    # font is a variable in global namespace

    while True:
        if ResolutionMenu.resolution == (800, 600):
            # [...]

            if button2.collidepoint((mx, my)):
                if Click:
                    OptionsMenu()

                    # create new font with new size
                    font = pygame.font.SysFont(None, settings.TextSize) 

            # [...]
def OptionsMenu():  
    global settings   # settings is a variable in global namespace

    screen = pygame.display.set_mode((800, 600))
    # settings = GuiSettings() # <--- DELETE use the existing object instead

    # [...]

关于python - 文本大小变化持久性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64679912/

相关文章:

python - 如何在 Python 中散列变量?

python - 箭头键通过 Gtk.FlowBox.select_child() 忽略选择

python pygame 如何淡入音量?

python - Pygame,改变我整个游戏的分辨率

python - 如何在 Python 中渲染一个等距的基于图 block 的世界?

python - 如何使用pygame在python中移动图像?

python - 更新 Pandas Dataframe 列 A 中的所有值,仅当 B 中的值不为零时才使用列 B 的值

python - 使用 Git 部署到我的服务器

python - 使用正则表达式从Python中的SQL查询中删除别名?

python - 如何使用 Sprite 组和杀死 Sprite 组