在pygame不使用图片做一个按钮的效果https://blog.csdn.net/zhangenter/article/details/89609946
之后,继续尝试做编辑框
下面是最新的效果图
主要代码
bf_common.py 控件基类
# -*- coding=utf-8 -*-
import threading
import pygame
from pygame.locals import MOUSEBUTTONDOWN
class BFControlId(object):
_instance_lock = threading.Lock()
def __init__(self):
self.id = 1
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(BFControlId, "_instance"):
BFControlId._instance = BFControlId(*args, **kwargs)
return BFControlId._instance
def get_new_id(self):
self.id += 1
return self.id
class BFBase(object):
def __init__(self):
self.panel = None
def clear_foucs(self):
pass
CLICK_EFFECT_TIME = 100
DEFAULT_FONT = pygame.font.Font(u'syht.otf', 28)
bf_button.py 按钮类
# -*- coding=utf-8 -*-
import threading
import pygame
from pygame.locals import MOUSEBUTTONDOWN
from bf_common import BFControlId,BFBase,DEFAULT_FONT
CLICK_EFFECT_TIME = 100
class BFButton(BFBase):
def __init__(self, parent, rect, text='Button', click=None):
self.x,self.y,self.width,self.height = rect
self.bg_color = (225,225,225)
self.parent = parent
self.surface = parent.subsurface(rect)
self.is_hover = False
self.in_click = False
self.click_loss_time = 0
self.click_event_id = -1
self.ctl_id = BFControlId().instance().get_new_id()
self._text = text
self._click = click
self._visible = True
self.init_font()
def init_font(self):
font = DEFAULT_FONT
white = 100, 100, 100
self.textImage = font.render(self._text, True, white)
w, h = self.textImage.get_size()
self._tx = (self.width - w) / 2
self._ty = (self.height - h) / 2
@property
def text(self):
return self._text
@text.setter
def text(self, value):
self._text = value
self.init_font()
@property
def click(self):
return self._click
@click.setter
def click(self, value):
self._click = value
@property
def visible(self):
return self._visible
@visible.setter
def visible(self, value):
self._visible = value
def update(self, event):
if self.in_click and event.type == self.click_event_id:
if self._click: self._click(self)
self.click_event_id = -1
return
x, y = pygame.mouse.get_pos()
if x > self.x and x < self.x + self.width and y > self.y and y < self.y + self.height:
self.is_hover = True
if event.type == MOUSEBUTTONDOWN:
pressed_array = pygame.mouse.get_pressed()
if pressed_array[0]:
self.in_click = True
if self.panel: self.panel.clear_foucs()
self.click_loss_time = pygame.time.get_ticks() + CLICK_EFFECT_TIME
self.click_event_id = pygame.USEREVENT+self.ctl_id
pygame.time.set_timer(self.click_event_id,CLICK_EFFECT_TIME-10)
else:
self.is_hover = False
def draw(self):
if self.in_click:
if self.click_loss_time < pygame.time.get_ticks():
self.in_click = False
if not self._visible:
return
if self.in_click:
r,g,b = self.bg_color
k = 0.95
self.surface.fill((r*k, g*k, b*k))
else:
self.surface.fill(self.bg_color)
if self.is_hover:
pygame.draw.rect(self.surface, (0,0,0), (0,0,self.width,self.height), 1)
pygame.draw.rect(self.surface, (100,100,100), (0,0,self.width-1,self.height-1), 1)
layers = 5
r_step = (210-170)/layers
g_step = (225-205)/layers
for i in range(layers):
pygame.draw.rect(self.surface, (170+r_step*i, 205+g_step*i, 255), (i, i, self.width - 2 - i*2, self.height - 2 - i*2), 1)
else:
self.surface.fill(self.bg_color)
pygame.draw.rect(self.surface, (0,0,0), (0,0,self.width,self.height), 1)
pygame.draw.rect(self.surface, (100,100,100), (0,0,self.width-1,self.height-1), 1)
pygame.draw.rect(self.surface, self.bg_color, (0,0,self.width-2,self.height-2), 1)
self.surface.blit(self.textImage, (self._tx, self._ty))
class BFButtonGroup(object):
def __init__(self):
self.btn_list = []
def add_button(self, button):
self.btn_list.append(button)
def make_button(self, screen, rect, text='Button', click=None):
button = BFButton(screen, rect,text=text,click=click)
self.add_button(button)
def update(self, event):
for button in self.btn_list: button.update(event)
def draw(self):
for button in self.btn_list: button.draw()
bf_edit.py 编辑框类
# -*- coding=utf-8 -*-
import time
import threading
import platform
import pygame
from pygame.locals import MOUSEBUTTONDOWN,KEYDOWN,SCRAP_TEXT
from bf_common import BFControlId,BFBase,DEFAULT_FONT
CLICK_EFFECT_TIME = 100
class BFEdit(BFBase):
def __init__(self, parent, rect, text='Button', click=None):
self.x,self.y,self.width,self.height = rect
self.bg_color = (255,255,255)
self.parent = parent
self.surface = parent.subsurface(rect)
self.in_edit = False
self.in_click = False
self.click_loss_time = 0
self.click_event_id = -1
self.ctl_id = BFControlId().instance().get_new_id()
self._text = text
self._visible = True
self.init_font()
def clear_foucs(self):
self.in_edit = False
def init_font(self):
font = DEFAULT_FONT
white = 100, 100, 100
self.textImage = font.render(self._text, True, white)
self.cursorImage = font.render('|', True, (170,205,255))
w, h = self.textImage.get_size()
self._tx = (self.width - w) / 2
self._ty = (self.height - h) / 2
self._cx = (self.width + w) / 2
self._cy = (self.height - h) / 2
@property
def text(self):
return self._text
@text.setter
def text(self, value):
self._text = value
self.init_font()
@property
def visible(self):
return self._visible
@visible.setter
def visible(self, value):
self._visible = value
def update(self, event):
if self.in_edit and event.type == KEYDOWN:
if event.key == 8:
if len(self._text)>0:
self.text = self._text[:-1]
elif event.key == 118 and (event.mod == 64 or event.mod==1024):
scrap_text = pygame.scrap.get(SCRAP_TEXT)
if scrap_text:
if 'Windows' in platform.platform():
scrap_text = scrap_text.decode('gbk').strip('\x00')
self.text = self._text+scrap_text
else:
self.text = self._text+event.unicode
if self.in_click and event.type == self.click_event_id:
self.in_edit = True
self.click_event_id = -1
return
x, y = pygame.mouse.get_pos()
if x > self.x and x < self.x + self.width and y > self.y and y < self.y + self.height:
if event.type == MOUSEBUTTONDOWN:
pressed_array = pygame.mouse.get_pressed()
if pressed_array[0]:
self.in_click = True
if self.panel: self.panel.clear_foucs()
self.click_loss_time = pygame.time.get_ticks() + CLICK_EFFECT_TIME
self.click_event_id = pygame.USEREVENT+self.ctl_id
pygame.time.set_timer(self.click_event_id,CLICK_EFFECT_TIME-10)
def draw(self):
if not self._visible:
return
# if self.in_edit:
# r,g,b = self.bg_color
# k = 0.95
# self.surface.fill((r*k, g*k, b*k))
# else:
# self.surface.fill(self.bg_color)
if self.in_edit:
layers = 2
r_step = (210-170)/layers
g_step = (225-205)/layers
for i in range(layers):
pygame.draw.rect(self.surface, (170+r_step*i, 205+g_step*i, 255), (i, i, self.width - i*2, self.height - i*2), 1)
pygame.draw.rect(self.surface, (100,100,100), (2,2,self.width-4,self.height-4), 1)
pygame.draw.rect(self.surface, (225,225,225), (3,3,self.width-6,self.height-6), 1)
else:
self.surface.fill(self.bg_color)
pygame.draw.rect(self.surface, (100,100,100), (1,1,self.width-2,self.height-2), 1)
pygame.draw.rect(self.surface, (225,225,225), (2,2,self.width-4,self.height-4), 1)
# pygame.draw.rect(self.surface, (0,0,0), (0,0,self.width,self.height), 1)
self.surface.blit(self.textImage, (self._tx, self._ty))
if self.in_edit:
if int(time.time()*2.5)%3 != 0:
self.surface.blit(self.cursorImage, (self._cx, self._cy))
bf_panel 面板类
便于统一管理面板上的所有控件
# -*- coding=utf-8 -*-
import threading
import pygame
class BFPanel(object):
def __init__(self):
self.ctl_list = []
def add_control(self, ctl):
ctl.panel = self
self.ctl_list.append(ctl)
def clear_foucs(self):
for ctl in self.ctl_list: ctl.clear_foucs()
def update(self, event):
for ctl in self.ctl_list: ctl.update(event)
def draw(self):
for ctl in self.ctl_list: ctl.draw()
测试代码
# -*- coding=utf-8 -*-
import pygame
pygame.init()
screen = pygame.display.set_mode((400,400))
pygame.scrap.init()
from bf_edit import BFEdit
from bf_button import BFButton
from bf_panel import BFPanel
screencaption = pygame.display.set_caption('bf control')
def do_click1(btn):
pygame.display.set_caption('i click %s,ctl id is %s' % (btn._text,btn.ctl_id))
btn.text = 'be click'
def do_click2(btn):
btn.visible = False
def do_click3(btn):
pygame.quit()
exit()
btn_panel = BFPanel()
btn_panel.add_control(BFButton(screen, (120,20,160,40),text=u'测试',click=do_click1))
btn_panel.add_control(BFButton(screen, (120,70,160,40),text='Hide',click=do_click2))
btn_panel.add_control(BFButton(screen, (120,120,160,40),text='Quit',click=do_click3))
edit1 = BFEdit(screen, (120,170,160,40),text='test1')
btn_panel.add_control(edit1)
edit2 = BFEdit(screen, (120,220,160,40),text='test2')
btn_panel.add_control(edit2)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
btn_panel.update(event)
screen.fill((255,255,255))
btn_panel.draw()
pygame.display.update()
目前编辑框支持效果主要有:输入大小写字母及符号,按回退键盘删除最后一个字母,按ctrl+v粘贴文本进来,目前运行效果如下
2019-12-1 17:17支持了中文