2017-04-23 13 views
0

私はWindowsでたくさんのGDI +を使用していましたが、いくつかのビットマップ/イメージをメモリに作成しようとしていましたので、後で描画する必要はありません。PyGame - Draw in Memory

GDI +でメモリにビットマップを描画するのは簡単でしたが、PyGameを使用してPythonで行う方法はわかりません。メモリに描画するチュートリアルやドキュメントは見つかりません。

現在いくつかのボタンを作成しようとしています。これは、単色の矩形、境界線、およびテキストの一部です。 2回目に3回を描画するのはあまり集中的ではありませんが、3より1つのグラフィックを描画するのはまだそれほど強力ではありません(さらに、ウィンドウのようなボタンのいくつかの状態があります。

答えて

0

パイガームではできませんでしたが、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 
+0

あなたの問題を解決した場合は、回答を受け入れてください。これは将来の読者に役立つでしょう。 –

+0

24時間タイムアウト前に解決策として自分の答えをマークすることができました。 – Siver

関連する問題