我试图制作一个瓦片地图制作器,在尝试获取 png 文件(瓦片表)时偶然发现了一个问题,askopenfile 函数崩溃了,这是按钮代码
self.tilemap_file_button = Button(self.Display,
self.display_size[0]-100,
10,
32,
32,
image=self.tilemap_file_sprite,
onClick=lambda:self.tile_map_button_pressed())
tile_map_button_pressed 函数
def tile_map_button_pressed(self):
tilesheet = filedialog.askopenfile()
整个事情
import sys
import pygame as py
import pygame_widgets
from pygame_widgets.button import Button
import tkinter
from tkinter import filedialog
root = tkinter.Tk()
root.withdraw()
root.call('wm', 'attributes', '.', '-topmost', True)
#from tkinter.filedialog import askopenfilename
class app:
def __init__(self)->None:
py.init()
self.clock = py.time.Clock()
self.WINDOW_HIEGHT,self.WINDOW_WIDTH = 800,800
self.Display = py.display.set_mode((self.WINDOW_WIDTH,self.WINDOW_HIEGHT),py.RESIZABLE)
self.display_size = self.Display.get_size()
self.RUNNING = True
self.window_scale = 1
self.tile_size = 32
self.Tile_rect = [self.tile_size,self.tile_size]
self.posX,self.posY = 0,0
#start mouse at middle so at (0,0) it doesen't go top left
self.mouse_pos = (self.WINDOW_WIDTH/2,self.WINDOW_HIEGHT/2)
self.font = py.font.Font(None, 36)
self.cord_text = self.font.render(f'pos: {self.posX},{self.posY}', True, (255, 255, 255))
self.grid = self.Tile_map_grid(self.Tile_rect,self.Display)
self.grid_posX,self.grid_posY=0,0
self.show_sprite = py.image.load("show_sprite.png")
self.tilemap_file_sprite = py.image.load("tile_map.png")
self.show_background = True
self.mouse_pressed = False
self.handling_events = False
self.MOUSE_MOTION_ALLOWED = True
self.grabbed = False
self.show_grid = True
self.initialize_tilesheet=False
self.background_height = 50
self.a = 0
self.show_button = Button(self.Display,
self.display_size[0]-50,
10,
32,
32,
image=self.show_sprite,
onClick= lambda :self.show_button_pressed()
)
self.tilemap_file_button = Button(self.Display,
self.display_size[0]-100,
10,
32,
32,
image=self.tilemap_file_sprite,
onClick=lambda:self.tile_map_button_pressed())
def main_loop(self,FPS):
LastFrameTick = 0
while self.RUNNING:
print('is running')
tick = py.time.get_ticks()
self.delta = (tick-LastFrameTick)/1000.0
#if its outside of window dont change mouse position
self.update_mouse_pos()
updated_position =self.update_position(self.mouse_pos, self.Display, 100)
self.posX += updated_position[0]
self.posY += updated_position[1]
self.update_grid_pos()
self.Display.fill((70,70,70))
if (not self.grabbed) and self.show_grid:
self.Display.blit(self.grid,(-self.tile_size*self.window_scale
-self.posX+self.grid_posX,-self.tile_size*self.window_scale-self.posY+self.grid_posY))
middle_point = py.draw.circle(self.Display,(0,0,0),(0-self.posX,0-self.posY),5*self.window_scale,20)
if self.show_background:
self.background()
if self.initialize_tilesheet:
filedialog.askopenfilename()
self.initialize_tilesheet=False
self.handling_events = self.handle_event()
py.display.update()
self.clock.tick(FPS)
LastFrameTick = tick
def handle_event(self):
keys = py.key.get_pressed()
events = py.event.get()
for event in events:
if event.type == py.MOUSEBUTTONDOWN or self.mouse_pressed:
self.mouse_pressed = True
if event.type == py.MOUSEBUTTONUP:
self.mouse_pressed = False
if self.mouse_pressed and event.type ==py.MOUSEMOTION:
self.grabbed = True
else:
self.grabbed = False
if event.type == py.KEYUP:
if keys[py.K_g]:
self.show_grid = not self.show_grid
if keys[py.K_s]:
self.show_background = not self.show_background
filedialog.askopenfilename()
if keys[py.K_EQUALS]:
self.ZoomIn()
elif keys[py.K_MINUS] :
self.ZoomOut()
if event.type == py.VIDEORESIZE:
self.display_size = self.Display.get_size()
self.grid = self.Tile_map_grid(py.Vector2(self.tile_size*self.window_scale),self.Display)
self.show_button._x = self.display_size[0]-50
self.tilemap_file_button._x = self.display_size[0]-100
if event.type == py.QUIT:
self.exit()
pygame_widgets.update(events)
def exit(self):
py.quit()
sys.exit()
def update_mouse_pos(self):
if py.mouse.get_focused() and self.MOUSE_MOTION_ALLOWED:
self.mouse_pos = py.mouse.get_pos()
if py.mouse.get_focused() and not self.MOUSE_MOTION_ALLOWED:
py.mouse.set_pos(self.mouse_pos)
def Cords(self):
self.cord_text = self.font.render(f'pos: {int(self.posX)},{int(self.posY)}', True, (255, 255, 255))
self.Display.blit(self.cord_text, (10, 10))
def Tile_map_grid(self,Tile_rect,Display)->py.Surface:
window_size = Display.get_size()
grid_size = window_size+py.Vector2(Tile_rect[0]*2)
grid = py.surface.Surface(grid_size)
grid.fill((70, 70, 70))
for row in range(int((window_size[1]+Tile_rect[1]*4)/Tile_rect[0])):
for tile in range(int((window_size[0]+Tile_rect[0]*4)/Tile_rect[1])):
py.draw.rect(grid, (255, 255, 255), [tile*Tile_rect[0], row*Tile_rect[1], Tile_rect[0], Tile_rect[1]], 1)
return grid
def update_position(self,mousep,window,Speed)->None:
Speed = int(Speed * self.display_size[0] /1000 * self.window_scale)
self.mouse_rel = py.mouse.get_rel() * Speed
if self.grabbed:
return (-self.mouse_rel[0]*self.delta*100,-self.mouse_rel[1]*self.delta*100)
window_size = window.get_size()
corner_width = 160
edge_width = 70
corners = {
'top_left':(corner_width,0,
corner_width+self.background_height,self.background_height,
-Speed*self.delta,-Speed*self.delta)
,'down_right':(window_size[0],window_size[0]-corner_width
,window_size[1],window_size[1]-corner_width,
Speed*self.delta,Speed*self.delta),
'top_right':(window_size[0],window_size[0]-corner_width
,corner_width+self.background_height,self.background_height,
+Speed*self.delta,-Speed*self.delta)
,'down_left':(corner_width,0,window_size[1],window_size[1]-corner_width,-Speed*self.delta,Speed*self.delta)
}
edges = {
'top':(edge_width+50,50,0,-Speed*1.4*self.delta,1)
,'bottom':(window_size[1],window_size[1]-edge_width,0,+Speed*1.4*self.delta,1),
'left':(edge_width,-edge_width,-Speed*1.4*self.delta,0,0)
,'right':(window_size[0],window_size[-0]-edge_width,Speed*1.4*self.delta,0,0)}
for corner in corners:
if (mousep[0]<corners[corner][0] and mousep[0]>corners[corner][1]
and mousep[1]<corners[corner][2] and mousep[1]>corners[corner][3]) :
return (corners[corner][4],corners[corner][5])
for edge in edges:
if mousep[1] < self.background_height:
continue
if mousep[edges[edge][4] ] < edges[edge][0] and mousep[edges[edge][4] ] > edges[edge][1]:
return (edges[edge][2],edges[edge][3])
return (0,0)
def ZoomIn(self)->None:
if self.window_scale > 1.9:return
self.window_scale+=0.1
self.grid = self.Tile_map_grid(py.Vector2(self.tile_size*self.window_scale),self.Display)
def ZoomOut(self)->None:
if self.window_scale < 0.7: return
self.window_scale -= 0.1
self.grid = self.Tile_map_grid(py.Vector2(self.tile_size * self.window_scale), self.Display)
file_path = filedialog.askopenfilename()
def update_grid_pos(self):
self.grid_posX = int(self.posX/(self.tile_size*self.window_scale))*self.tile_size*self.window_scale
self.grid_posY = int(self.posY /(self.tile_size*self.window_scale))*self.tile_size * self.window_scale
def show_button_pressed(self):
self.show_background = not self.show_background
def background(self):
top_background = py.draw.rect(self.Display, (45, 45, 45), [0, 0, self.display_size[0], self.background_height])
self.Cords()
def tile_map_button_pressed(self):
tilesheet = filedialog.askopenfile()
if __name__ == "__main__":
new_app = app()
new_app.main_loop(60)
我尝试在 (tile_map_button_pressed) 时将变量更改为 true 执行,然后在主循环中运行askopenfile(当它为真时),但这没有起作用
这是一个较小的问题示例,单击按钮会使askopenfile崩溃
import pygame
import pygame_widgets
from pygame_widgets.button import Button
import tkinter
from tkinter import filedialog
pygame.init()
win = pygame.display.set_mode((600, 600))
def button_clicked():
filedialog.askopenfilename()
button = Button(
win,
150,
150,
300,
150,
text='button',
fontSize=50,
margin=20,
inactiveColour=(150, 150, 150),
hoverColour=(170, 170, 170),
pressedColour=(200, 200, 200),
radius=20,
onClick=lambda: button_clicked()
)
run = True
while run:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
run = False
quit()
win.fill((255, 255, 255))
pygame_widgets.update(events)
pygame.display.update()
我不知道它为什么起作用,但使用 onRelease 可以修复它
import pygame
import pygame_widgets
from pygame_widgets.button import Button
import tkinter
from tkinter import filedialog
pygame.init()
win = pygame.display.set_mode((600, 600))
def button_clicked():
"""Create a Tk file dialog and cleanup when finished"""
top = tkinter.Tk()
top.withdraw() # hide window
file_name = tkinter.filedialog.askopenfilename(parent=top)
top.destroy()
return file_name
a = lambda :True
button = Button(
win,
150,
150,
300,
150,
text='button',
fontSize=50,
margin=20,
inactiveColour=(150, 150, 150),
hoverColour=(170, 170, 170),
pressedColour=(200, 200, 200),
radius=20,
onRelease=button_clicked
)
run=True
while run:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
run = False
quit()
win.fill((255, 255, 255))
pygame_widgets.update(events)
pygame.display.update()