1

im tryna make a python gui application using pygame but now i realised that its meant for games specifically and not for regular applications... ive done the most part but now im stuck at a point where i wanna take input in a paragraph box from a user but i cant really find a way to do it, is there really a way to do that or do i have to switch to a completely different module and start from scratch

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)

this is a sample code of my login page where i take input but its just the username and password, how do i take inputs in paragraphs because when i try this the text goes outside the screen

PsyQuake
  • 45
  • 8
  • 1
    **Never** post crucial information, especially code or errors, in images or external links, as mentioned in [mre]. All crucial information should be included in the question itself as formatted text. Links and images are almost always only for additional info that can aid the question. – Ted Klein Bergman Feb 07 '22 at 16:01
  • oh im sorry but then how do i put all of the files in this question? – PsyQuake Feb 07 '22 at 16:03
  • You need to create a [mcve]. You try to create an example that illustrates the issue you have, with minimal but complete code. Then you put the code in code blocks. You can have several code blocks for each file – Ted Klein Bergman Feb 07 '22 at 16:04
  • edited now, thanks for the info! – PsyQuake Feb 07 '22 at 16:10

1 Answers1

3

You must combine the answers to the following questions:

Use the code for the text input box form How to create a text input box with pygame? and render the texture using the drawText function from Rendering text with multiple lines in pygame.

Minimal example based on the code from the question:

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)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174