我在Windows上使用了很多GDI +,并尝试在内存中创建一些位图/图像,以便以后可以绘制它们而无需绘制它们的所有部分。
在GDI +中很容易在内存中绘制位图,但我不知道如何使用PyGame在Python中执行此操作,而且我无法在内存中找到任何教程/文档。
目前正在尝试创建一些按钮。它将是一个纯色矩形,边框和一些文字。不是非常密集地每次画几次3次,但绘制1个图形的强度仍然不高于3.(另外按钮会有几种状态,比如窗口。就像按下或鼠标悬停在按钮上一样)
答案 0 :(得分:0)
想出来,用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