Python/Pygame在离开窗口时在Pygame中换行文本

9avjhtql  于 12个月前  发布在  Python
关注(0)|答案(3)|浏览(198)

我有一个呈现文本的文本函数。

def textFunc(font,msg,color,x,y,center):
    text_render = font.render(msg,True,color)
    text_rect = text_render.get_rect()
    
    #If center is true, then the X,Y will be used as the center
    if center == True:
        text_rect.center = (x,y)
    else:
        text_rect = (x,y)
    game_display.blit(text_render,text_rect)

字符串
然而,我的msg字符串太长,它将呈现在窗口之外。
有没有一种方法可以让我的文本在我的窗口中注册太长,所以在文本的开头下面继续注册?类似于计算机自动注册的方式。
例如:

bybem2ql

bybem2ql1#

没有自动的解决方案。你必须自己实现文本换行,并逐行逐词地绘制文本。
幸运的是PyGame wiki提供了一个函数来完成这个任务。参见PyGame wiki Simple Text Wrapping for pygame
我扩展了这个函数,并添加了一个额外的参数,它提供了 * 左 * 或 * 右 * 对齐的文本,* 居中 * 的文本甚至 * 块 * 模式:

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 ""

字符串
最小示例:

repl.it/@Rabbid76/PyGame-TextWrap

import pygame

pygame.init()
font = pygame.font.SysFont(None, 40)

msg = "Simple function that will draw text and wrap it to fit the rect passed.  If there is any text that will not fit into the box, the remaining text will be returned."
textRect = pygame.Rect(100, 100, 300, 300)

window = pygame.display.set_mode((500, 500))
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill((255, 255, 255))
    pygame.draw.rect(window, (0, 0, 0), textRect, 1)
    drawTextRect = textRect.inflate(-5, -5)
    drawText(window, msg, (0, 0, 0), drawTextRect, font, textAlignBlock, True)
    pygame.display.flip()

e3bfsja2

e3bfsja22#

pygame-cepygame的现代分支)版本2.1.4pygame.Font.render开始,现在支持换行符("\n")和换行长度(换行前的像素宽度)。
因此,您只需将想要的文本传递给pygame.Font.render,并指定窗口宽度作为最后一个参数,以便在文本达到窗口宽度时自动换行。由于此方法还不接受关键字参数,因此您还必须提供背景颜色参数,它可以是None,也可以提供alpha值为0的颜色值。

下面是一个简短的代码示例:

import pygame

WIDTH, HEIGHT = 640, 360
FPS = 60

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

font = pygame.Font(None, 32)
text_surf = font.render(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
    "In feugiat imperdiet velit, et dictum arcu malesuada in.",
    True,
    "black",
    None,  # or (0, 0, 0, 0) for example
    WIDTH,
)

running = True
while running:
    clock.tick(FPS)
    screen.fill("white")

    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            running = False

    screen.blit(text_surf, (0, 0))

    pygame.display.flip()

字符串

结果:

x1c 0d1x的数据
此外,要安装最新版本的pygame-ce,只需按照以下步骤操作:

  1. pip uninstall pygame(为了避免冲突,只有在已经安装了pygame的情况下才必须这样做)
  2. pip install pygame-ce
    1.享受新的和闪亮的功能
    关于分叉的更多信息可以在这里找到:Pygame: Community Edition Announcement您也可以加入pygame的官方discord服务器(-ce):https://discord.gg/pygame
fv2wmkja

fv2wmkja3#

我不喜欢把简单的事情搞得复杂化,最好的解决方案在文档中,顺便说一句,pygame.freetype模块是pygame.font的替代品。

import pygame.freetype as ft

def render_text(surface, text, size, color):
    font = ft.SysFont('consolas', size)
    words = text.split(' ')
    w, h = surface.get_size()
    line_spacing = font.get_sized_height() + 2
    x, y = 0, line_spacing
    space = font.get_rect(' ')

    for word in words:
        bounds = font.get_rect(word)
        if x + bounds.width + bounds.x >= w:
            x, y = 0, y + line_spacing
        font.render_to(surface, (x, y - bounds.y), None, color)
        x += bounds.width + space.width

字符串
就是这样。例如:

import pygame as pg

ORANGE = (253, 156, 0)

surface = pg.Surface((400, 200))
render_text(surface, ("This is a test -.,\` 09 ") * 1000, 14, ORANGE)


通过导入pygame.freetypepg.init()将负责初始化,否则您也需要初始化ft,因此只需导入它。您可能还想知道当text = None时文本是如何呈现的。这是因为我们重新呈现传递给bounds = self.font.get_rect(word)的文本

相关问题