如何使用类显示与矩形位置相关的字体?

时间:2017-08-26 20:57:22

标签: python class methods fonts pygame

我正在努力重写一段工作代码 - 我以更面向对象的方式编写,并且不知道如何将字体(显示位置)附加到3个移动的部分。换句话说,当我移动那些rects时,我希望将数字与其位置相关联。 强烈建议任何改进此代码的建议。

import sys
import pygame as pg
WIDTH = 800
HEIGHT = 600
WHITE = (255, 255, 255)
SCREEN = pg.display.set_mode((WIDTH, HEIGHT))
clock = pg.time.Clock()
pg.font.init()

class Rectangle(pg.sprite.Sprite):

    def __init__(self, color, width, height, x , y):

        super().__init__()

        self.width = width
        self.height = height
        self.color = color
        self.image = pg.Surface((width, 3*140 + height),pg.SRCALPHA)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

        for z in range(0, 3 * 140, 140):
            pg.draw.rect(self.image, color, (0, z, self.width, self.height))

    def draw(self, screen):
        screen.blit(self.image, self.rect)
        return int(self.rect.y)

    def update(self):
        self.rect.y += event.rel[1]

    def rect_y(self):
        return self.rect.y

class Font(Rectangle):

    def __init__(self, color, width, height, x , y):
        super().__init__( color, width, height, x , y)

        self.font_a = pg.font.Font(None, 20)
        self.text = self.font_a.render(str(abs(int(object1.rect_y()))), True, (0,0,0))
        self.text_rect = self.text.get_rect()
        self.text_rect.y = Rectangle.rect_y(self)

object1 = Rectangle((50,100,100), 30, 100, 110 , 120)
selected1 = False
done = False

while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.MOUSEBUTTONDOWN:
            if object1.rect.collidepoint(event.pos):
                selected1 = True

        elif event.type == pg.MOUSEBUTTONUP:
            selected1 = False

        elif event.type == pg.MOUSEMOTION:
            if selected1:
                object1.update()

    SCREEN.fill(WHITE)

    font1 = Font((50,100,100), 30, 100, 110 , 120)
    SCREEN.blit(font1.text, font1.rect)

    object1.draw(SCREEN)
    pg.display.update()
    clock.tick(60)

if __name__ == '__main__':
    pg.init()
    pg.quit()
    sys.exit()

1 个答案:

答案 0 :(得分:1)

我将Font个对象(我将该类重命名为Label)作为属性添加到Rectangle个实例中。如果您需要多个标签,可以将它们放入列表中。我提供了Rectangle handle_event方法,我将MOUSEMOTION事件传递给我以更新其self.rect,然后矩形将事件传递给其标签,以便他们可以更新他们的立场。

要存储精灵实例,您可以使用pygame.sprite.Group(示例中为all_sprites),它允许您通过调用all_sprites.update()all_sprites.draw(SCREEN)来更新所有包含的精灵。 all_sprites.update()在这种情况下实际上没用,因为精灵没有update方法(我只是想告诉你应该如何在主循环中调用它)。

import pygame as pg


pg.init()

WHITE = (255, 255, 255)
SCREEN = pg.display.set_mode((800, 600))
FONT_A = pg.font.Font(None, 20)
clock = pg.time.Clock()


class Rectangle(pg.sprite.Sprite):

    def __init__(self, color, width, height, x, y, all_sprites):
        super().__init__()
        self.color = color
        self.image = pg.Surface((width, 3*140 + height), pg.SRCALPHA)
        self.rect = self.image.get_rect(topleft=(x, y))
        # If you need multiple labels, you can put them into a list.
        # You could also create and add them in the for loop below.
        self.labels = [Label(self.rect.right+3, self.rect.top, (0,0,0)),
                       Label(self.rect.right+3, self.rect.top+140, (0,0,0))]
        all_sprites.add(self.labels)

        for z in range(0, 3*140, 140):
            pg.draw.rect(self.image, color, (0, z, width, height))

    def handle_event(self, event):
        self.rect.y += event.rel[1]
        # Pass the event to the labels, so that they can handle it themselves.
        for label in self.labels:
            label.handle_event(event)


class Label(pg.sprite.Sprite):

    def __init__(self, x, y, color):
        super().__init__()
        self.color = color
        self.image = FONT_A.render(str(abs(y)), True, self.color)
        self.rect = self.image.get_rect(topleft=(x, y))

    def handle_event(self, event):
        self.rect.y += event.rel[1]
        self.image = FONT_A.render(str(abs(self.rect.y)), True, self.color)


def main():
    # Create a sprite group which will contain all sprite instances.
    # To update and draw the sprites you can just call its .update and .draw
    # methods.
    all_sprites = pg.sprite.Group()
    # Pass the group to the Rectangle, because we need to add the labels.
    object1 = Rectangle((50,100,100), 30, 100, 110, 120, all_sprites)
    all_sprites.add(object1)

    selected1 = False
    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.MOUSEBUTTONDOWN:
                if object1.rect.collidepoint(event.pos):
                    selected1 = True
            elif event.type == pg.MOUSEBUTTONUP:
                selected1 = False
            elif event.type == pg.MOUSEMOTION:
                if selected1:
                    # Pass the event to the object's handle_event method,
                    # where it uses it to update its rect and labels.
                    object1.handle_event(event)

        all_sprites.update()

        SCREEN.fill(WHITE)
        all_sprites.draw(SCREEN)

        pg.display.update()
        clock.tick(60)

if __name__ == '__main__':
    main()
    pg.quit()

附录:如果所有标签都显示相同的值(在这种情况下是rects的顶部位置),则可以将此值传递给标签实例并将其添加为属性。然后在handle_event方法中更新它并使用它来渲染字体表面。

class Rectangle(pg.sprite.Sprite):

    def __init__(self, color, width, height, x, y, all_sprites):
        super().__init__()
        self.color = color
        self.image = pg.Surface((width, 3*140 + height), pg.SRCALPHA)
        self.rect = self.image.get_rect(topleft=(x, y))
        # Pass another argument (the `value`) to the labels.
        self.labels = [Label(self.rect.right+3, self.rect.top, self.rect.top, (0,0,0)),
                       Label(self.rect.right+3, self.rect.top+140, self.rect.top, (0,0,0))]
        all_sprites.add(self.labels)

        for z in range(0, 3*140, 140):
            pg.draw.rect(self.image, color, (0, z, width, height))

    def handle_event(self, event):
        self.rect.y += event.rel[1]
        for label in self.labels:
            label.handle_event(event)


class Label(pg.sprite.Sprite):

    def __init__(self, x, y, value, color):
        super().__init__()
        self.value = value
        self.color = color
        self.image = FONT_A.render(str(abs(self.value)), True, self.color)
        self.rect = self.image.get_rect(topleft=(x, y))

    def handle_event(self, event):
        # Update the self.value as well and use it to render the new font surface.
        self.value += event.rel[1]
        self.rect.y += event.rel[1]
        self.image = FONT_A.render(str(abs(self.value)), True, self.color)