pygame不使用图片做一个编辑框的效果

在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支持了中文
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰风漫天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值