【无标题】

项目场景:

最近想个孩子写个问答类的小游戏,需要用到文本输入功能,在网上没有找到合适的解决方案,于是用tkinter的entry组件写了个,但是发现在其他电脑上运行会出现游戏对象坐标与输入框坐标不一致的情况,向请教下大神有没有pygame自带的文本输入功能的组件


问题描述

# coding:utf-8
import os

os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame
import tkinter as tk
import threading
import multiprocessing
from PIL import ImageGrab, ImageFilter
import  win32gui
import pyglet
import sys

def doGrabAllScreen(width, height):
    p = ImageGrab.grab((0, 0, width, height))  # 截图。因PIL的问题,必须将显示设置里的缩放比例调成100%,否则截取尺寸出错
    p = p.resize((int(width * 0.9), int(height * 0.9)))  # 缩放截图
    p = p.filter(ImageFilter.SMOOTH)
    #p = p.filter(ImageFilter.BLUR)
    return p.tobytes(), p.size  # 将截图的byte数据及截图尺寸返回


'''计数器'''


class Count(object):
    '''统计操作次数,可通过操作次数达到后执行某项任务'''

    def __init__(self):
        self.count = 0
        self.timer = 0

    def add(self):
        '''计数加1'''
        self.count += 1

    def update(self):
        '''更新计数器,
            游戏窗口设置刷新率为每秒60帧,
                判断如果1秒内没有再次执行操作,计数将归零
            '''
        if self.timer >= 30:
            self.count = 0
            self.timer = 0
        if self.count != 0:
            self.timer += 1

    def reSet(self):
        '''重置计数器'''
        self.count = 0
        self.timer = 0

    def start(self, counts: int, obj):
        '''设置计数达到值后执行任务,
                为达到并发效果,创建线程来执行
        '''
        if self.count == counts:
            self.reSet()
            obj()


'''鼠标位置统计'''


class Mouse(object):
    '''计算鼠标当前位置与对象x,y坐标初始点的距离
        '''

    def __init__(self):
        self.x = 0
        self.y = 0

    def start(self, x, y, rect_x, rect_y):  # 开始

        self.x = x - rect_x
        self.y = y - rect_y
        return self.x, self.y

    def move(self, x, y):  # 移动
        return x - self.x, y - self.y


'''文字输入事件'''


class Entry(object):
    def __init__(self, var, x, y, width, height):
        '''双击游戏窗口的文本对象后实例化文本框,可输入自定义字符,
        按回车键或游戏窗口其他地方绘制新的文本对象
        '''
        self.size = var.size - 10
        self.x = x + 10
        self.y = y + 30
        self.lens = len(var.cache)

        self.singsize = int(self.size * 4 / 3)  # tkinter 字体占用像素
        self.widith =self.singsize
        for i in var.cache:
            try:
                i.encode('ascii')
            except:

                self.widith += self.singsize
            else:
                self.widith += int(self.singsize * 0.5)
            #self.win.geometry("%sx%s+%s+%s" % (self.widith, self.height, self.x, self.y))
        self.height = height
        self.root = var
        self.win = tk.Tk()
        if self.win.winfo_x() + self.widith > self.root.w:
            self.widith = self.root.w - self.win.winfo_x()
        self.win.geometry("%sx%s+%s+%s" % (self.widith, self.height, self.x, self.y))
        self.entry = tk.Entry(self.win, font=("幼圆", self.size), bd=0, justify=tk.LEFT)
        self.entry.pack(fill=tk.BOTH, expand=tk.YES)
        self.entry.insert(tk.END, var.cache)
        self.entry.select_range(0, tk.END)

        self.win.attributes("-transparentcolor", "blue")
        # self.win.wm_attributes('-topmost', 1)
        self.entry.focus()  # 将输入框置顶
        self.win.overrideredirect(True)  # 隐藏文本块边框
        self.entry.bind('<Return>', self.bind)
        self.entry.bind('<KeyRelease>', self.bind_KeyRelease)
        self.win.bind("<FocusOut>", self.bind_FousOut)
        self.win.mainloop()

    def bind_FousOut(self, event):
        '''文本框失去焦点后,
                如果文本框有文本则绘制文本框的内容,
                    否则绘制输入前的内容
        '''
        if not self.entry.get():
            self.root.var(self.root.cache, 1)
        else:
            self.root.var(self.entry.get(), 1)
        self.win.destroy()
        self.root.entry = False

    def bind_KeyRelease(self, event):
        '''键盘按键抬起后重新布局输入框长度
                中文为单个字符的长度,
                    英文为半个字符的长度
            '''

        self.widith = self.singsize

        for i in self.entry.get():
            try:
                i.encode('ascii')
            except:

                self.widith += self.singsize
            else:
                self.widith += int(self.singsize * 0.5)
            if self.win.winfo_x()+self.widith > self.root.w:
                self.widith = self.root.w - self.win.winfo_x()
            self.win.geometry("%sx%s+%s+%s" % (self.widith, self.height, self.x, self.y))

    def bind(self, event):
        '''按下回车键后关闭输入框并在游戏窗口绘制文本'''
        var = self.entry.get()
        self.win.destroy()
        self.root.entry = False
        self.root.var(var, 1)


class Font(object):
    '''创建文本对象'''

    def __init__(self, root):  # root --> 窗口对象
        self.cache = ""  # 缓存,启用输入框后,缓存输入前的文本对象
        self.text = ""
        self.fg = None
        self.bg = None
        self.ttf = "./fonts/SIMYOU.TTF"  # 字体文件
        self.size = 40  # 设置字体大小
        self.font = pygame.font.Font(self.ttf, self.size)
        self.root = root  # 窗口对象
        self.moves = False  # 鼠标拖动检测
        self.mouse = Mouse()  # 鼠标位置统计
        self.t = None
        # self.rect=None
        self.entry = None  # 文本输入框显示检测
        self.x = 0
        self.y = 0

    def set(self, fg: tuple, bg: tuple = None):
        # 设置参数
        self.fg = fg
        self.bg = bg

    def var(self, text, sets):
        # 创建文字
        self.text = text
        self.t = self.font.render(text, True, self.fg, self.bg)
        self.rect = self.t.get_rect()
        if sets == 0:
            self.x = self.rect.x
            self.y = self.rect.y
        elif sets == 1:
            self.rect.x = self.x
            self.rect.y = self.y
        self.width = self.rect.width
        self.height = self.rect.height

    def location(self, x, y):
        # 改变位置
        if self.rect:
            self.x = x
            self.y = y
            self.rect.x = x
            self.rect.y = y

    def detect(self, mouse_x, mouse_y):  # 检测是否点击
        return self.rect.collidepoint(mouse_x, mouse_y)

    def blit(self):  # 绘制
        self.root.blit(self.t, (self.rect.x, self.rect.y))

    def button(self, x, y):  # 按下
        self.moves = True
        self.mouse.start(x, y, self.rect.x, self.rect.y)

    def move(self, x, y):  # 移动
        movx, movy = self.mouse.move(x, y)
        self.rect.x = movx
        self.rect.y = movy

    def up(self):  # 抬起
        self.moves = False

    def box(self):
        '''启动输入框'''
        if not self.entry:
            self.cache = self.text
            self.entry = True
            hwnd = win32gui.FindWindow(None, '拼图')
            rect = win32gui.GetWindowRect(hwnd)
            x = rect[0]
            y = rect[1]
            self.x = self.rect.left
            self.y = self.rect.top
            self.w = rect[2] - x
            self.h = rect[3] - y
            t = threading.Thread(target=Entry,
                                 args=(self, self.rect.left + x, self.rect.top + y, self.rect.width, self.rect.height,))
            t.setDaemon(True)
            t.start()
            self.var("", 1)


if __name__ == '__main__':
    filename = "imges/screen/screens.jpg"
    multiprocessing.freeze_support()  # 在windows下不支持子进程,运行此函数让windows支持子进程
    fontpath = ".\\fonts\\SIMYOU.TTF"
    pyglet.font.add_file(fontpath)
    pyglet.font.load(fontpath)
    pygame.init()
    '''设置窗口'''
    screen = pygame.display.Info()  # 获取屏幕信息
    byte_img, size = doGrabAllScreen(screen.current_w, screen.current_h)
    bg_img = pygame.image.frombuffer(byte_img, size, "RGB")
    bg_img.set_alpha(100)

    width, height = int(screen.current_w * 0.9), int(screen.current_h * 0.9)  # 计算窗口尺寸
    root = pygame.display.set_mode((width, height))  # 设置窗口尺寸 返回一个根目录用以绘制图形
    pygame.display.set_caption("拼图")

    # ico=pygame.image.load("imges/ico/icos.ico")
    # pygame.display.set_icon(ico)
    count1 = Count()
    font = Font(root)
    font.set((255, 255, 253))
    font.var("在这里输入文字", 0)
    font.location(500, 200)
    time = pygame.time.Clock()  # 实例化时钟类

    while True:
        for event in pygame.event.get():
            mouse_x, mouse_y = pygame.mouse.get_pos()
            if event.type == pygame.QUIT:  # 监听是否退出
                pygame.quit()
                sys.exit(0)
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:

                    if font.detect(mouse_x, mouse_y):
                        count1.add()
                        font.button(mouse_x, mouse_y)
            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:

                    font.up()
            if event.type == pygame.MOUSEMOTION:
                if font.moves:

                    font.move(mouse_x, mouse_y)

        root.fill((100, 100, 100))
        root.blit(bg_img, (0, 0))
        #pygame.draw.rect(root,(230,230,230),(100,50,300,200),0)
        count1.start(2, font.box)
        count1.update()
        font.blit()

        pygame.display.update()
        time.tick(60)  # 设置每秒循环30帧

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值