Tkinter Python 3.6中Canvas的create_window无法使用求助
搞定Canvas create_window 失效的问题
嘿,我看你在自定义InventorySlot组件时,想把控件放到Canvas上而非用grid/pack,但create_window没正常工作对吧?这事儿我碰到过,来给你拆解下问题和解决办法。
先说说你代码里可能踩的坑:
- 你的
InventorySlot继承自tk.Frame,但初始化后没给Canvas做布局(比如用pack/grid让它占满整个Frame)——Canvas都没显示,create_window的控件当然看不到 - 可能你创建控件时父容器没设成Canvas,或者调用
create_window时坐标没给对 - 代码里
self.options.update(kwa...没写完,不过先不管这个,先解决核心问题
给你一个修正后的完整示例代码,你可以直接参考:
import tkinter as tk from tkinter import ttk class Main: def __init__(self): self.root = tk.Tk() self.root.geometry('500x500') # 加个边距方便看组件边界 self.test = InventorySlot(self.root) self.test.grid(padx=20, pady=20) self.root.mainloop() class InventorySlot(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) # 先创建Canvas,给个背景色方便观察 self.canvas = tk.Canvas(self, bg="#eeeeee", width=200, height=200) # 用pack让Canvas填满整个Frame,也可以用grid,记得配权重 self.canvas.pack(fill="both", expand=True) # 要放到Canvas里的控件,父容器必须是这个Canvas! self.slot_label = ttk.Label(self.canvas, text="物品槽", background="white") self.slot_button = ttk.Button(self.canvas, text="点击操作") # 用create_window把控件放到Canvas的指定坐标(这里是中心偏上/偏下) # 返回的ID可以用来后续修改这个控件的位置或属性 self.label_id = self.canvas.create_window(100, 50, window=self.slot_label) self.button_id = self.canvas.create_window(100, 150, window=self.slot_button) if __name__ == "__main__": app = Main()
再划几个关键要点:
- Canvas必须先布局:一定要用
pack(fill="both", expand=True)或者grid(row=0, column=0, sticky="nsew")让Canvas在Frame里显示出来,不然里面的控件根本没地方放 - 控件父容器要对:所有要通过
create_window放到Canvas上的控件,父容器必须是这个Canvas,不能是Frame,否则挂载不上 - 坐标要明确:
create_window的前两个参数是控件在Canvas上的x、y坐标,根据Canvas的尺寸调整就行 - 如果要支持缩放:可以给Frame的行列加权重,比如在
InventorySlot的__init__里加:
然后Canvas用self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1)grid(row=0, column=0, sticky="nsew"),这样Frame缩放时Canvas也会跟着放大缩小
如果之前你的create_window没生效,大概率是Canvas没布局或者控件父容器错了,对照上面的代码改改应该就能解决啦~
内容的提问来源于stack exchange,提问作者Hasty Basher




