项目场景:
最近想个孩子写个问答类的小游戏,需要用到文本输入功能,在网上没有找到合适的解决方案,于是用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帧

2139

被折叠的 条评论
为什么被折叠?



