pygame-绘制内存



我在Windows上使用了大量的GDI ,并且正在尝试在内存中创建一些位图/图像,以便以后绘制它们而无需绘制所有片段。

在GDI 中很容易在内存中绘制位图,但是我不知道如何使用Pygame在Python中进行操作,并且在内存中绘制时找不到任何教程/文档。

当前试图创建一些按钮。它将是一个纯色矩形,边框和一些文字。第二次绘制几次3件事不是很密集,但是绘制1个图形比3的密集程度不高。

弄清楚了,不能用pygame做到这一点,但PIL可以做到!

controls = []
SS_LEFT = 0x0000
SS_RIGHT = 0x0002
BS_BOTTOM = 0x0800
BS_CENTER = 0x0300
BS_DEFPUSHBUTTON = 0x0001
BS_MULTILINE = 0x2000
BS_TOP = 0x0400
BS_VCENTER = 0x0C00
BS_ICON = 0x0040
BS_BITMAP = 0x0080
BS_FLAT = 0x8000
BS_NOTIFY = 0x4000
BUTTON_PROPERTIES = {'bk_color_normal': (51, 51, 51), 'border_color_normal': (51, 51, 51), 'text_color_normal': (241, 241, 241),
                     'bk_color_hot': (16, 16, 16), 'border_color_hot': (16, 16, 16), 'text_color_hot': (241, 241, 241),
                     'bk_color_pressed': (0, 122, 204), 'border_color_pressed': (0, 122, 204), 'text_color_pressed': (241, 241, 241),
                     'bk_color_disabled': (82, 82, 82), 'border_color_disabled': (118, 118, 118), 'text_color_disabled': (124, 124, 124),
                     'px_border': 3}
def create_button(text, x, y, width, height,
                  properties=BUTTON_PROPERTIES,
                  style=BS_CENTER | BS_VCENTER | BS_MULTILINE):
    rect = pygame.Rect(properties['px_border'], properties['px_border'], width - (properties['px_border'] * 2), height - (properties['px_border'] * 2))
    tmp_font = ImageFont.truetype('segoeui.ttf', 12)
    lines_of_string = format_string(text, tmp_font, rect).splitlines()
    bk_normal = Image.new('RGBA', size=(width, height), color=properties['border_color_normal'])
    bk_hot = Image.new('RGBA', size=(width, height), color=properties['border_color_hot'])
    bk_pressed = Image.new('RGBA', size=(width, height), color=properties['border_color_pressed'])
    bk_disabled = Image.new('RGBA', size=(width, height), color=properties['border_color_disabled'])
    image_normal = ImageDraw.Draw(bk_normal)
    image_hot = ImageDraw.Draw(bk_hot)
    image_pressed = ImageDraw.Draw(bk_pressed)
    image_disabled = ImageDraw.Draw(bk_disabled)
    image_normal.rectangle([(properties['px_border'], properties['px_border']),
                            (width - properties['px_border'] - 1, height - properties['px_border'] - 1)],
                           properties['bk_color_normal'])
    image_hot.rectangle([(properties['px_border'], properties['px_border']),
                         (width - properties['px_border'] - 1, height - properties['px_border'] - 1)],
                        properties['bk_color_hot'])
    image_pressed.rectangle([(properties['px_border'], properties['px_border']),
                             (width - properties['px_border'] - 1, height - properties['px_border'] - 1)],
                            properties['bk_color_pressed'])
    image_disabled.rectangle([(properties['px_border'], properties['px_border']),
                              (width - properties['px_border'] - 1, height - properties['px_border'] - 1)],
                             properties['bk_color_disabled'])
    if lines_of_string:
        i = 0
        text_y = 0
        font_height = tmp_font.getsize(text)[1] + 3
        # Get vertical alignment
        if style & BS_VCENTER == BS_VCENTER:
            if style & BS_MULTILINE == BS_MULTILINE:
                # get the number of lines that will fit in the area
                while i < len(lines_of_string):
                    if i * font_height < rect.height:
                        i += 1
                    else:
                        break
                # calculate the starting position of y
                # will center the number of lines it can draw
                text_y = int(rect.y + int(rect.height / 2) - ((i * font_height) / 2))
                # text_y is going to start above the actual start position of y, re-adjust
                if text_y < rect.y:
                    text_y = rect.y
            else:
                lines_of_string = lines_of_string[:1]
                text_y = rect[1] + (rect[3] / 2) - (font_height / 2)
        elif style & BS_BOTTOM == BS_BOTTOM:
            lines_of_string = reversed(lines_of_string)
            text_y = rect[3] - font_height
            font_height *= -1
        elif style & BS_TOP == BS_TOP:
            text_y = rect.y
        for line in lines_of_string:
            #
            if style & SS_RIGHT == SS_RIGHT:
                # check that the text_y value is not above the top of the rect
                if text_y < rect.top:
                    break
            # if the text_y value + the current height needed to draw this line goes below the bottom
            elif text_y + font_height > rect.bottom:
                break
            # get the width of this line
            line_width = tmp_font.getsize(line)[0]
            # draw in the center
            if style & BS_CENTER == BS_CENTER:
                row_x = rect.left + ((rect.width / 2) - (line_width / 2))
                row_y = text_y
            # draw on the right side
            elif style & SS_RIGHT == SS_RIGHT:
                row_x = rect.right - line_width
                row_y = text_y
            # draw on the left side
            else:
                row_x = rect.left
                row_y = text_y
            image_normal.text((row_x, row_y), line, font=tmp_font, fill=properties['text_color_normal'])
            image_hot.text((row_x, row_y), line, font=tmp_font, fill=properties['text_color_hot'])
            image_pressed.text((row_x, row_y), line, font=tmp_font, fill=properties['text_color_pressed'])
            image_disabled.text((row_x, row_y), line, font=tmp_font, fill=properties['text_color_disabled'])
            # adjust the text_y position
            text_y += font_height
    # Add the newly created buttons to the controls list
    # can use surface.blit(controls[id]['hot'], controls[id]['rect']) to draw the button
    controls.append({'draw': True,
                     'state': 'normal',
                     'dbl_click': False,
                     'on_event': None,
                     'on_dbl_click': None,
                     'timer': 0,
                     'dbl_timer': time.clock(),
                     'rect': pygame.Rect(x, y, width, height),
                     'normal': pygame.image.fromstring(bk_normal.tobytes(), bk_normal.size, bk_normal.mode),
                     'hot': pygame.image.fromstring(bk_hot.tobytes(), bk_hot.size, bk_hot.mode),
                     'pressed': pygame.image.fromstring(bk_pressed.tobytes(), bk_pressed.size, bk_pressed.mode),
                     'disabled': pygame.image.fromstring(bk_disabled.tobytes(), bk_disabled.size, bk_disabled.mode)})
    bk_normal.save('normal.png')
    bk_hot.save('hot.png')
    bk_pressed.save('pressed.png')
    bk_disabled.save('disabled.png')
    return len(controls)
def format_string(string, font, rect):
    if not isinstance(string, str):
        string = str(string)
    if str(type(font)).find('pygame') > -1:
        size_func = font.size
    else:
        size_func = font.getsize
    lines_of_string = string.splitlines()
    # string that will hold the newly formatted string
    new_string = ''
    for line in lines_of_string:
        if line == '':
            new_string += "n"
        else:
            while line:
                i = 0
                # start building this line
                while size_func(line[:i])[0] < rect.width and i < len(line):
                    i += 1
                # i is less than the length of this line
                if i < len(line):
                    # find the last word in this line up until the i position
                    i = line.rfind(' ', 0, i) + 1
                    # no words found, this string is way too long to be drawn in this area
                    if i == 0:
                        return ''
                    else:
                        # append the fitted line to new_string, trimming the trailing ' ' character and add the linefeed
                        new_string += line[:i - 1] + 'n'
                # this whole line fits
                else:
                    i = len(line)
                    new_string += line[:i] + 'n'
                # trim the string we took out of this line
                line = line[i:]
    # return the properly formatted string, complete with newlines
    return new_string

最新更新