pygame实现中文文本框(用系统输入法)

版本要求:pygame.2.0.0以上

        今天在用PyQt5创建文本框时,突发奇想,能不能用pygame实现文本框?pygame什么都行,就文本框不行,经过一番搜寻后,我在pygame安装目录里找到了一个textinput.py文件,内容如下:(不同版本的pygame文件不一样)

#!/usr/bin/env python
""" pg.examples.textinput

A little "console" where you can write in text.

Shows how to use the TEXTEDITING and TEXTINPUT events.
"""
import sys
import os
from typing import List

import pygame
import pygame as pg
import pygame.freetype as freetype

# This environment variable is important
# If not added the candidate list will not show
os.environ["SDL_IME_SHOW_UI"] = "1"


class TextInput:
    """
    A simple TextInput class that allows you to receive inputs in pygame.
    """

    # Add font name for each language,
    # otherwise some text can't be correctly displayed.
    FONT_NAMES = ",".join(
        str(x)
        for x in [
            "notosanscjktcregular",
            "notosansmonocjktcregular",
            "notosansregular,",
            "microsoftjhengheimicrosoftjhengheiuilight",
            "microsoftyaheimicrosoftyaheiuilight",
            "msgothicmsuigothicmspgothic",
            "msmincho",
            "Arial",
        ]
    )

    def __init__(
        self, prompt: str, pos, screen_dimensions, print_event: bool, text_color="white"
    ) -> None:
        self.prompt = prompt
        self.print_event = print_event
        # position of chatlist and chatbox
        self.CHAT_LIST_POS = pg.Rect((pos[0], pos[1] + 50), (screen_dimensions[0], 400))
        self.CHAT_BOX_POS = pg.Rect(pos, (screen_dimensions[1], 40))
        self.CHAT_LIST_MAXSIZE = 20

        self._ime_editing = False
        self._ime_text = ""
        self._ime_text_pos = 0
        self._ime_editing_text = ""
        self._ime_editing_pos = 0
        self.chat_list: List[str] = []

        # Freetype
        # The font name can be a comma separated list
        # of font names to search for.
        self.font = freetype.SysFont(self.FONT_NAMES, 24)
        self.font_small = freetype.SysFont(self.FONT_NAMES, 16)
        self.text_color = text_color

        print("Using font: " + self.font.name)

    def update(self, events) -> None:
        """
        Updates the text input widget
        """
        for event in events:
            if event.type == pg.KEYDOWN:
                if self.print_event:
                    print(event)

                if self._ime_editing:
                    if len(self._ime_editing_text) == 0:
                        self._ime_editing = False
                    continue

                if event.key == pg.K_BACKSPACE:
                    if len(self._ime_text) > 0 and self._ime_text_pos > 0:
                        self._ime_text = (
                            self._ime_text[0 : self._ime_text_pos - 1]
                            + self._ime_text[self._ime_text_pos :]
                        )
                        self._ime_text_pos = max(0, self._ime_text_pos - 1)

                elif event.key == pg.K_DELETE:
                    self._ime_text = (
                        self._ime_text[0 : self._ime_text_pos]
                        + self._ime_text[self._ime_text_pos + 1 :]
                    )
                elif event.key == pg.K_LEFT:
                    self._ime_text_pos = max(0, self._ime_text_pos - 1)
                elif event.key == pg.K_RIGHT:
                    self._ime_text_pos = min(
                        len(self._ime_text), self._ime_text_pos + 1
                    )
                # Handle ENTER key
                elif event.key in [pg.K_RETURN, pg.K_KP_ENTER]:
                    # Block if we have no text to append
                    if len(self._ime_text) == 0:
                        continue

                    # Append chat list
                    self.chat_list.append(self._ime_text)
                    if len(self.chat_list) > self.CHAT_LIST_MAXSIZE:
                        self.chat_list.pop(0)
                    self._ime_text = ""
                    self._ime_text_pos = 0

            elif event.type == pg.TEXTEDITING:
                if self.print_event:
                    print(event)
                self._ime_editing = True
                self._ime_editing_text = event.text
                self._ime_editing_pos = event.start

            elif event.type == pg.TEXTINPUT:
                if self.print_event:
                    print(event)
                self._ime_editing = False
                self._ime_editing_text = ""
                self._ime_text = (
                    self._ime_text[0 : self._ime_text_pos]
                    + event.text
                    + self._ime_text[self._ime_text_pos :]
                )
                self._ime_text_pos += len(event.text)

    def draw(self, screen: pygame.Surface) -> None:
        """
        Draws the text input widget onto the provided surface
        """

        # Chat List updates
        chat_height = self.CHAT_LIST_POS.height / self.CHAT_LIST_MAXSIZE
        for i, chat in enumerate(self.chat_list):
            self.font_small.render_to(
                screen,
                (self.CHAT_LIST_POS.x, self.CHAT_LIST_POS.y + i * chat_height),
                chat,
                self.text_color,
            )

        # Chat box updates
        start_pos = self.CHAT_BOX_POS.copy()
        ime_text_l = self.prompt + self._ime_text[0 : self._ime_text_pos]
        ime_text_m = (
            self._ime_editing_text[0 : self._ime_editing_pos]
            + "|"
            + self._ime_editing_text[self._ime_editing_pos :]
        )
        ime_text_r = self._ime_text[self._ime_text_pos :]

        rect_text_l = self.font.render_to(
            screen, start_pos, ime_text_l, self.text_color
        )
        start_pos.x += rect_text_l.width

        # Editing texts should be underlined
        rect_text_m = self.font.render_to(
            screen,
            start_pos,
            ime_text_m,
            self.text_color,
            None,
            freetype.STYLE_UNDERLINE,
        )
        start_pos.x += rect_text_m.width
        self.font.render_to(screen, start_pos, ime_text_r, self.text_color)


class Game:
    """
    A class that handles the game's events, mainloop etc.
    """

    # CONSTANTS
    # Frames per second, the general speed of the program
    FPS = 50
    # Size of window
    SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
    BG_COLOR = "black"

    def __init__(self, caption: str) -> None:
        # Initialize
        pg.init()
        self.screen = pg.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
        pg.display.set_caption(caption)
        self.clock = pg.time.Clock()

        # Text input
        # Set to true or add 'showevent' in argv to see IME and KEYDOWN events
        self.print_event = "showevent" in sys.argv
        self.text_input = TextInput(
            prompt="> ",
            pos=(0, 20),
            screen_dimensions=(self.SCREEN_WIDTH, self.SCREEN_HEIGHT),
            print_event=self.print_event,
            text_color="green",
        )

    def main_loop(self) -> None:
        pg.key.start_text_input()
        input_rect = pg.Rect(80, 80, 320, 40)
        pg.key.set_text_input_rect(input_rect)

        while True:
            events = pg.event.get()
            for event in events:
                if event.type == pg.QUIT:
                    pg.quit()
                    return

            self.text_input.update(events)

            # Screen updates
            self.screen.fill(self.BG_COLOR)
            self.text_input.draw(self.screen)

            pg.display.update()
            self.clock.tick(self.FPS)


# Main loop process
def main():
    game = Game("Text Input Example")
    game.main_loop()


if __name__ == "__main__":
    main()

(只要把FONT_NAMES的定义改成:

FONT_NAMES = ",".join(
        str(x)
        for x in [
            "宋体,SimSun",
            "notosanscjktcregular",
            "notosansmonocjktcregular",
            "notosansregular,",
            "microsoftjhengheimicrosoftjhengheiuilight",
            "microsoftyaheimicrosoftyaheiuilight",
            "msgothicmsuigothicmspgothic",
            "msmincho",
            "Arial",
        ]
    )

就可以显示中文了。

在这里,我们只用关注os.environ["SDL_IME_SHOW_UI"] = "1",pg.key.start_text_input(),pg.TEXTINPUT事件和pg.key.set_text_input_rect(input_rect)就可以了。

os.environ["SDL_IME_SHOW_UI"] = "1"

这条代码是让SDL显示输入法,SDL默认不显示输入法。需要注意的是,此代码应当在pygame.init()之后,在pygame.display.set_mode之前。

pg.TEXTINPUT

这个事件是用输入法输入文字时才触发的,这个事件有text属性,用来接收输入法输入的文字。

pg.key.stop_text_input()

这条代码可以让输入法暂时隐藏,不过此代码应当在pygame.display.set_mode之后。

pg.key.start_text_input()

这条代码可以让暂时隐藏的输入法显示,不过此代码也应当在pygame.display.set_mode之后。

pygame.key.set_text_input_rect(input_rect)

这条代码可以让输入法候选框移动位置,参数是input_rect,input_rect的类型是pygame.Rect。

这是一个示例:
 

import pygame
import os
pygame.init()
os.environ['SDL_IME_SHOW_UI'] = "1"
screen = pygame.display.set_mode((640, 640))
r = True
while r:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            r = False
        elif event.type == pygame.TEXTINPUT:
            print(event.text)

pygame.quit()

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Pygame并没有提供内置的文本框功能,但我们可以使用其他方法来实现文本输入框。 一种常见的方法是使用Pygame中的文本渲染功能和事件处理来创建一个模拟文本框。下面是一个简单的示例代码,展示了如何在Pygame中创建一个基本的文本输入框: ```python import pygame from pygame.locals import * pygame.init() # 设置窗口大小和标题 screen_width = 640 screen_height = 480 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption('Text Input Example') # 设置字体和文本颜色 font = pygame.font.Font(None, 32) text_color = (255, 255, 255) # 设置文本输入框的初始值和位置 input_box = pygame.Rect(200, 200, 140, 32) input_text = '' running = True while running: for event in pygame.event.get(): if event.type == QUIT: running = False elif event.type == KEYDOWN: if event.key == K_BACKSPACE: # 删除最后一个字符 input_text = input_text[:-1] else: # 添加输入字符到文本框 input_text += event.unicode screen.fill((0, 0, 0)) # 绘制文本输入框 pygame.draw.rect(screen, (255, 255, 255), input_box, 2) # 绘制文本 text_surface = font.render(input_text, True, text_color) screen.blit(text_surface, (input_box.x + 5, input_box.y + 5)) pygame.display.flip() pygame.quit() ``` 这个示例程序创建了一个简单的窗口,并在窗口中显示一个文本输入框。你可以使用键盘输入字符,按下退格键删除字符。输入的文本会在文本输入框的左上角渲染。 请注意,这只是一个基本的示例,你可能需要根据你的需求进行进一步的定制和优化。另外,还有一些第三方库可以提供更高级的文本输入框功能,如`pygame_textinput`等,你可以根据自己的需要选择使用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值