【问题标题】:Pygame - blitting text with an escape character or newline [duplicate]Pygame - 使用转义字符或换行符对文本进行 blitting [重复]
【发布时间】:2015-12-11 22:47:56
【问题描述】:

您好,我希望在 pygame 屏幕上添加一些文本。我的文字是在单词 recommened 之后有/包含一个换行符。

posX = (self.scrWidth * 1/8)
posY = (self.scrHeight * 1/8)
position = posX, posY
font = pygame.font.SysFont(self.font, self.fontSize)
if text == "INFO":
   text = """If you are learning to play, it is recommended
               you chose your own starting area."""
   label = font.render(text, True, self.fontColour)
   return label, position

return 给出 blit 的表面和位置。

我已经尝试使用三引号方法来包含空格,使用 \n。 我不知道我做错了什么。

【问题讨论】:

    标签: python-3.x pygame


    【解决方案1】:

    pygame.font.Font/SysFont().render() 不支持多行文本。

    这在文档here 中有说明。

    文本只能是单行:不呈现换行符。

    解决此问题的一种方法是呈现单行字符串列表。每行一个,然后将它们一个在另一个之下。

    例子:

    posX = (self.scrWidth * 1/8)
    posY = (self.scrHeight * 1/8)
    position = posX, posY
    font = pygame.font.SysFont(self.font, self.fontSize)
    if text == "INFO":
        text = ["If you are learning to play, it is recommended",
                "you chose your own starting area."]
        label = []
        for line in text: 
            label.append(font.render(text, True, self.fontColour))
        return label, position
    

    然后要对图像进行 blit,您可以使用另一个 for 循环,如下所示:

    for line in range(len(label)):
        surface.blit(label(line),(position[0],position[1]+(line*fontsize)+(15*line)))
    

    在blit的Y值中,值为:

    position[1]+(line*fontsize)+(15*line)
    

    这正是获取位置[0],这是之前的 posY 变量,并将其用作 blit 的最左上角位置。

    然后将 (line*fontsize) 添加到其中。因为 for 循环使用范围而不是列表项本身,所以行将是 1,2,3 等...,因此可以添加以将每个连续的行直接放在另一行的下方。

    最后,将 (15*line) 添加到其中。这就是我们如何获得空间之间的边距。常数,在本例中为 15,表示边距应该是多少像素。数字越大,差距越大,数字越小,差距越小。添加“线”的原因是为了补偿将上述线向下移动所述数量。如果您愿意,您可以去掉“*line”,看看这将如何导致线条开始重叠。

    【讨论】:

    • 感谢您的回复,我忘记了在找到答案后我问了这个问题。我也会发布我使用的答案。
    【解决方案2】:

    这是我在代码中找到并使用的 anwser。这会产生一个可以正常使用的文本表面。

    class TextRectException:
        def __init__(self, message=None):
                self.message = message
    
        def __str__(self):
            return self.message
    
    
    def multiLineSurface(string: str, font: pygame.font.Font, rect: pygame.rect.Rect, fontColour: tuple, BGColour: tuple, justification=0):
        """Returns a surface containing the passed text string, reformatted
        to fit within the given rect, word-wrapping as necessary. The text
        will be anti-aliased.
    
        Parameters
        ----------
        string - the text you wish to render. \n begins a new line.
        font - a Font object
        rect - a rect style giving the size of the surface requested.
        fontColour - a three-byte tuple of the rgb value of the
                 text color. ex (0, 0, 0) = BLACK
        BGColour - a three-byte tuple of the rgb value of the surface.
        justification - 0 (default) left-justified
                    1 horizontally centered
                    2 right-justified
    
        Returns
        -------
        Success - a surface object with the text rendered onto it.
        Failure - raises a TextRectException if the text won't fit onto the surface.
        """
    
        finalLines = []
        requestedLines = string.splitlines()
        # Create a series of lines that will fit on the provided
        # rectangle.
        for requestedLine in requestedLines:
            if font.size(requestedLine)[0] > rect.width:
                words = requestedLine.split(' ')
                # if any of our words are too long to fit, return.
                for word in words:
                    if font.size(word)[0] >= rect.width:
                        raise TextRectException("The word " + word + " is too long to fit in the rect passed.")
                # Start a new line
                accumulatedLine = ""
                for word in words:
                    testLine = accumulatedLine + word + " "
                    # Build the line while the words fit.
                    if font.size(testLine)[0] < rect.width:
                        accumulatedLine = testLine
                    else:
                        finalLines.append(accumulatedLine)
                        accumulatedLine = word + " "
                finalLines.append(accumulatedLine)
            else:
                finalLines.append(requestedLine)
    
        # Let's try to write the text out on the surface.
        surface = pygame.Surface(rect.size)
        surface.fill(BGColour)
        accumulatedHeight = 0
        for line in finalLines:
            if accumulatedHeight + font.size(line)[1] >= rect.height:
                 raise TextRectException("Once word-wrapped, the text string was too tall to fit in the rect.")
            if line != "":
                tempSurface = font.render(line, 1, fontColour)
            if justification == 0:
                surface.blit(tempSurface, (0, accumulatedHeight))
            elif justification == 1:
                surface.blit(tempSurface, ((rect.width - tempSurface.get_width()) / 2, accumulatedHeight))
            elif justification == 2:
                surface.blit(tempSurface, (rect.width - tempSurface.get_width(), accumulatedHeight))
            else:
                raise TextRectException("Invalid justification argument: " + str(justification))
            accumulatedHeight += font.size(line)[1]
        return surface
    

    【讨论】:

      猜你喜欢
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 2017-10-23
      • 2012-12-14
      相关资源
      最近更新 更多