使用输入法进行输入
在代码内加入os.environ["SDL_IME_SHOW_UI"] = "1"使用输入法,调用pygame.key.start_text_input()可以控制是否接收键盘输入事件,与之对应的为pygame.key.stop_text_input(),pygame.key.set_text_input_rect(rect: RectValue)这个函数为渲染输入文字的位置。
代码示例:
from rectangle import rectangle
from border import border
import pygame
import os
def find_closest_number(num, lst):
if len(lst):
closest_num = lst[0] # 将第一个数字设为初始的最接近数字
for n in lst:
if abs(num - n) < abs(num - closest_num):
closest_num = n
return closest_num
return -1
class textinput:
os.environ["SDL_IME_SHOW_UI"] = "1"
def __init__(self, screen, width, height, x, y, font=None):
self.screen = screen
self.text = ""
self.buf_text = ""
self.x = x
self.y = y
self.width = width
self.height = height
self.rect = rectangle(screen, width + 5, height, x, y, background_color=(255, 255, 255),
rect_border=border(1, (0, 0, 0)))
self.font = font if font is not None else pygame.font.SysFont("simhei", 20)
self.active = False
point = self.rect.get_coordinate()
pygame.key.set_text_input_rect((point.left, point.top + 10, point.width, point.height))
pygame.key.stop_text_input()
self.cursor = -1
def draw(self):
self.rect.draw()
if self.active:
font_range = self.font.size(self.text)
if font_range[0] <= self.width:
rect = self.rect.get_coordinate()
self.buf_text = self.text
self.screen.blit(self.font.render(self.text, True, (0, 0, 0)),
(rect.x, rect.y + (self.height / 2 - self.font.get_height() / 2)))
else:
res = 0
while True:
if self.font.size(self.text[res::])[0] <= self.width:
rect = self.rect.get_coordinate()
self.buf_text = self.text[res::]
self.screen.blit(self.font.render(self.text[res::], True, (0, 0, 0)),
(rect.x, rect.y + (self.height / 2 - self.font.get_height() / 2)))
break
res += 1
if self.cursor == -1:
font_size = self.font.size(self.text)
y_start = self.y + 3
y_end = self.y + self.height - 3
if font_size[0] <= self.width:
x = self.x + font_size[0] + 2
pygame.draw.line(self.screen, (0, 0, 0), (x, y_start), (x, y_end))
else:
x = self.width + 2 + self.x
pygame.draw.line(self.screen, (0, 0, 0), (x, y_start), (x, y_end))
else:
y_start = self.y + 3
y_end = self.y + self.height - 3
x = self.font.size(self.buf_text[0:self.cursor])[0] + self.x
pygame.draw.line(self.screen, (0, 0, 0), (x, y_start), (x, y_end))
else:
font_range = self.font.size(self.text)
if font_range[0] <= self.width:
rect = self.rect.get_coordinate()
self.buf_text = self.text
self.screen.blit(self.font.render(self.text, True, (0, 0, 0)),
(rect.x, rect.y + (self.height / 2 - self.font.get_height() / 2)))
else:
res = 0
while True:
if self.font.size(self.text[res::])[0] <= self.width:
rect = self.rect.get_coordinate()
self.buf_text = self.text[res::]
self.screen.blit(self.font.render(self.text[res::], True, (0, 0, 0)),
(rect.x, rect.y + (self.height / 2 - self.font.get_height() / 2)))
break
res += 1
def handel(self, event):
self.rect.handel(event)
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if self.rect.is_clicked(pygame.mouse.get_pos()):
self.active = True
pygame.key.start_text_input()
self.rect.border.color = self.rect.click_border_color
point = pygame.mouse.get_pos()
x_point = point[0] - self.x
x = [self.font.size(self.buf_text[:x])[0] for x in range(len(self.buf_text))]
n = find_closest_number(x_point, x)
try:
if x_point > max(x):
self.cursor = -1
else:
self.cursor = x.index(n)
except ValueError:
self.cursor = -1
else:
self.active = False
self.rect.border.color = (0, 0, 0)
if self.active:
if event.type == pygame.TEXTINPUT:
if self.cursor == -1:
self.text += event.text
point = self.rect.get_coordinate()
pygame.key.set_text_input_rect((point.left, point.top + 10, point.width, point.height))
else:
self.text = self.text[0:self.cursor] + event.text + self.text[self.cursor:]
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE: # 退格键
if self.cursor == -1:
self.text = self.text[:-1]
elif self.cursor == 0:
return
else:
self.text = self.text[:self.cursor-1] + self.text[self.cursor:]
self.cursor -= 1
def get_text(self):
return self.text
if __name__ == '__main__':
pygame.init()
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
running = True
inp = textinput(screen, 200, 30, 20, 100)
inp2 = textinput(screen, 200, 30, 20, 200)
while running:
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
inp.handel(event)
inp2.handel(event)
screen.fill((255, 255, 255))
inp.draw()
inp2.draw()
pygame.display.flip()
rectangle类代码
import pygame
from border import border
class rectangle:
def __init__(self, screen, width, height, x, y, background_color=None, rect_border=None, fix=False,
click_background_color=(255, 255, 255), click_border_color=(64, 160, 255)):
self.width = width
self.height = height
self.screen = screen
self.window_width = screen.get_width()
self.window_height = screen.get_height()
self.x = x
self.y = y
self.background_color = background_color if background_color is not None else (255, 255, 255)
self.click_background_color = click_background_color
self.click_border_color = click_border_color
self.background = self.background_color
self.border = rect_border if rect_border is not None else border(1, self.background_color)
self.selected = False
self.offset = False
self.fix = fix
def draw(self):
pygame.draw.rect(self.screen, self.border.color, (self.x, self.y, self.width, self.height))
pygame.draw.rect(self.screen, self.background,
(self.x+self.border.thickness, self.y+self.border.thickness,
self.width-(self.border.thickness*2), self.height-(self.border.thickness*2)))
def get_coordinate(self):
return pygame.Rect(self.x, self.y, self.width, self.height)
def set_coordinate(self, x, y):
self.x = x
self.y = y
if x <= 0:
self.x = 0
if x >= self.window_width-self.width:
self.x = self.window_width-self.width
if y <= 0:
self.y = 0
if y >= self.window_height-self.height:
self.y = self.window_height-self.height
def is_clicked(self, mouse_pos):
are = self.get_coordinate()
if are.collidepoint(mouse_pos):
return True
else:
return False
def handel(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and self.is_clicked(pygame.mouse.get_pos()):
self.selected = True
self.background = self.click_background_color
self.border.color = self.click_border_color
if self.fix:
point = pygame.mouse.get_pos()
self.offset = (point[0]-self.x, point[1]-self.y)
if event.type == pygame.MOUSEMOTION:
if self.selected and self.fix:
point = pygame.mouse.get_pos()
self.set_coordinate(point[0]-self.offset[0], point[1]-self.offset[1])
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
self.selected = False
self.background = self.background_color
if __name__ == '__main__':
pygame.init()
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
running = True
rect = rectangle(screen, 100, 100, 0, 0, fix=True, rect_border=border(1, (0, 255, 0)),background_color=(255, 255, 255))
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
rect.handel(event)
screen.fill((255,255,255))
rect.draw()
pygame.display.flip()
border类代码
class border:
def __init__(self, thickness=1, color=(0, 0, 0)):
self.thickness = thickness
self.color = color
pygame版本 pygame 2.5.1 (SDL 2.28.2, Python 3.6.6)