Tkinter网格异常问题:销毁方块后视觉消失的排查与解决
Tkinter图像揭示游戏开发:问题与解决
需求与初始实现
我正在用Python的Tkinter开发一款图像揭示游戏,核心功能是展示一张被可点击销毁的网格方块覆盖的图片。点击方块时销毁它并打印坐标,期望销毁方块后其余方块保持网格位置不变,逐步揭示下方图片,网格形态不发生变化。
我编写了以下最简版线性代码:
from tkinter import * from PIL import ImageTk, Image class Box: def __init__(self, parent, row, column, width, height): self.row = row self.column = column self.canvas = Canvas(parent, bg='black', width=width, height=height) self.canvas.grid(row=row, column=column, sticky=NSEW) self.canvas.bind('<Button-1>', self.destroy) def destroy(self, event): print('Destroyed box at', self.row, self.column) self.canvas.destroy() root = Tk() root.title('Image Reveal') root.state('zoomed') image_raw = None # 为图片创建容器框架 image_frame = Frame(root, highlightbackground="blue", highlightthickness=5) image_frame.pack(expand=True, anchor=CENTER, fill=BOTH, padx=0, pady=0) # 加载图片并放入标签 image_raw = Image.open('image.png') image = ImageTk.PhotoImage(image_raw) image_label = Label(image_frame, image=image, borderwidth=5, relief='ridge') image_label.pack(anchor=CENTER, expand=True) # 计算方块尺寸 image_label.update() width = image.width() height = image.height() column_amount = 10 row_amount = 10 box_width = width / column_amount box_height = height / row_amount # 创建铺满网格的方块 for row in range(row_amount): for column in range(column_amount): Box(image_label, row, column, box_width, box_height) root.mainloop()
异常现象
点击方块销毁后,其余方块视觉上消失,但仍可点击触发销毁日志,无法实现预期的网格保持效果。
优化与最终解决方案
在Lukas Krahbichler的帮助下先实现了大部分预期效果,但销毁整行或整列方块时会导致网格尺寸变化。最终通过将方块隐藏至图片下方替代销毁的方式解决问题(由于Canvas没有直接整体下移的方法,需调用tk原生命令)。
最终可用代码如下:
from tkinter import * from PIL import ImageTk, Image class Box: def __init__(self, root, image_frame, image_label, row, column): self.root = root self.row = row self.column = column self.image_label = image_label self.image_frame = image_frame self.visible = True self.canvas = Canvas(image_frame, bg='black') self.canvas.grid(row=row, column=column, sticky=NSEW, padx=5, pady=5) self.canvas.bind('<Button-1>', self.hide) def hide(self, event): # 将方块下移至图片下方实现隐藏 self.canvas.tk.call('lower', self.canvas._w, None) self.visible = False print('Hid box at', self.row, self.column) root = Tk() root.title('Image Reveal') root.state('zoomed') image_raw = None column_amount = 10 row_amount = 10 boxes = [] # 为图片创建容器框架 image_frame = Frame(root, highlightbackground="blue", highlightthickness=0) image_frame.pack(anchor=CENTER, fill=None, padx=0, pady=0) # 加载图片并放入标签 image_raw = Image.open('image.png') image = ImageTk.PhotoImage(image_raw) width = image.width() height = image.height() # 创建图片标签 image_label = Label(image_frame, image=image, borderwidth=0, relief='ridge') # 配置图片框架禁止自动调整尺寸 <----- 更新部分 image_frame.config(width=width, height=height) image_frame.grid_propagate(False) image_label.grid_propagate(False) # 将图片标签放入框架 image_label.grid(rowspan=row_amount, columnspan=column_amount, sticky="NSEW") # 配置网格权重 <----- 更新部分 for row in range(10): image_frame.rowconfigure(row, weight=1) for column in range(10): image_frame.columnconfigure(column, weight=1) # 更新图片标签状态 image_label.update() # 创建铺满网格的方块 for row in range(row_amount): for column in range(column_amount): box = Box(root, image_frame, image_label, row, column) boxes.append(box) root.mainloop()
内容的提问来源于stack exchange,提问作者Yamiko Hikari
相关产品推荐
相关产品推荐

