pygame中的段落输入

Paragraph input in pygame

我尝试使用 pygame 制作一个 python gui 应用程序,但现在我意识到它专门用于游戏而不是常规应用程序......我已经完成了大部分但现在我卡在了我想从用户的段落框中获取输入,但我真的找不到办法做到这一点,真的有办法做到这一点,还是我必须切换到一个完全不同的模块并从头开始

import pygame 

pygame.init()
screen = pygame.display.set_mode((600,600))
app_fps = pygame.time.Clock()
bg = pygame.image.load('Moment-Book/GUI/assets/login_bg.jpg')
font = pygame.font.Font(None,32)
active_color = pygame.Color('dodgerblue2')
inactive_color = pygame.Color('white')
back_button = pygame.image.load('Moment-Book/GUI/assets/back_button.png')

class InputBox():
    def __init__(self,max_len,x,y,width,height,text = ''):
        self.color = inactive_color
        self.len = max_len
        self.rect = pygame.Rect(x,y,width,height)
        self.text = text 
        self.text_surf = font.render(text,True,self.color)
        self.active = False

    def event_handler(self,event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                self.active = not self.active 
            else:
                self.active = False
        self.color = active_color if self.active else inactive_color
    
        if event.type == pygame.KEYDOWN:
            if self.active:
                if event.key == pygame.K_RETURN:
                    print(self.text)
                    self.text = ''
                elif event.key == pygame.K_BACKSPACE or len(self.text)>self.len:
                    self.text = self.text[:-1]
                else:
                    self.text += event.unicode
                
                self.text_surf = font.render(self.text,True,self.color)

    def draw(self,screen):
        screen.blit(self.text_surf, (self.rect.x+5,self.rect.y+5))
        pygame.draw.rect(screen,self.color,self.rect,2,border_radius=2)

    def update(self):
        width = max(200, self.text_surf.get_width()+10)
        self.rect.w = width 
        
back_rect = pygame.Rect(30,30,45,45)

def login():
    inputbox = InputBox(15,180,305,140,32)
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False 
            if event.type == pygame.MOUSEBUTTONDOWN:
                if back_rect.collidepoint(event.pos):
                    running = False  
            inputbox.event_handler(event)
        
        screen.blit(bg,(-167,0))
        screen.blit(back_button,(back_rect.topleft,back_rect.bottomleft))
        

        inputbox.draw(screen)
        inputbox.update()

        pygame.display.update()
        app_fps.tick(60)

这是我的登录页面的示例代码,我在其中输入,但它只是用户名和密码,我如何在段落中输入,因为当我尝试这个时,文本会超出屏幕

您必须结合以下问题的答案:

使用文本输入框形式的代码 并使用 中的 drawText 函数渲染纹理。

基于问题代码的最小示例:

import pygame 

pygame.init()
screen = pygame.display.set_mode((600,600))
app_fps = pygame.time.Clock()
font = pygame.font.SysFont(None,32)
active_color = pygame.Color('dodgerblue2')
inactive_color = pygame.Color('white')

textAlignLeft = 0
textAlignRight = 1
textAlignCenter = 2
textAlignBlock = 3

def drawText(surface, text, color, rect, font, align=textAlignLeft, aa=False, bkg=None):
    lineSpacing = -2
    spaceWidth, fontHeight = font.size(" ")[0], font.size("Tg")[1]

    listOfWords = text.split(" ")
    if bkg:
        imageList = [font.render(word, 1, color, bkg) for word in listOfWords]
        for image in imageList: image.set_colorkey(bkg)
    else:
        imageList = [font.render(word, aa, color) for word in listOfWords]

    maxLen = rect[2]
    lineLenList = [0]
    lineList = [[]]
    for image in imageList:
        width = image.get_width()
        lineLen = lineLenList[-1] + len(lineList[-1]) * spaceWidth + width
        if len(lineList[-1]) == 0 or lineLen <= maxLen:
            lineLenList[-1] += width
            lineList[-1].append(image)
        else:
            lineLenList.append(width)
            lineList.append([image])

    lineBottom = rect[1]
    lastLine = 0
    for lineLen, lineImages in zip(lineLenList, lineList):
        lineLeft = rect[0]
        if align == textAlignRight:
            lineLeft += + rect[2] - lineLen - spaceWidth * (len(lineImages)-1)
        elif align == textAlignCenter:
            lineLeft += (rect[2] - lineLen - spaceWidth * (len(lineImages)-1)) // 2
        elif align == textAlignBlock and len(lineImages) > 1:
            spaceWidth = (rect[2] - lineLen) // (len(lineImages)-1)
        if lineBottom + fontHeight > rect[1] + rect[3]:
            break
        lastLine += 1
        for i, image in enumerate(lineImages):
            x, y = lineLeft + i*spaceWidth, lineBottom
            surface.blit(image, (round(x), y))
            lineLeft += image.get_width() 
        lineBottom += fontHeight + lineSpacing

    if lastLine < len(lineList):
        drawWords = sum([len(lineList[i]) for i in range(lastLine)])
        remainingText = ""
        for text in listOfWords[drawWords:]: remainingText += text + " "
        return remainingText
    return ""

class InputBox():
    def __init__(self,max_len,x,y,width,height,text = ''):
        self.color = inactive_color
        self.len = max_len
        self.rect = pygame.Rect(x,y,width,height)
        self.text = text 
        self.text_surf = font.render(text,True,self.color)
        self.active = False

    def event_handler(self,event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                self.active = not self.active 
            else:
                self.active = False
        self.color = active_color if self.active else inactive_color
    
        if event.type == pygame.KEYDOWN:
            if self.active:
                if event.key == pygame.K_RETURN:
                    self.text = ''
                elif event.key == pygame.K_BACKSPACE:
                    self.text = self.text[:-1]
                else:
                    self.text += event.unicode

    def draw(self,screen):
        pygame.draw.rect(screen, self.color, self.rect, 1)
        drawTextRect = self.rect.inflate(-5, -5)
        drawText(screen, self.text, self.color, drawTextRect, font, textAlignLeft, True)

    def update(self):
        pass
        
back_rect = pygame.Rect(30,30,45,45)

inputbox = InputBox(15,180,305,140,96)
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        inputbox.event_handler(event)
    
    screen.fill(0)        

    inputbox.update()
    inputbox.draw(screen)
    pygame.display.update()
    app_fps.tick(60)