You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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__里加:
    self.grid_rowconfigure(0, weight=1)
    self.grid_columnconfigure(0, weight=1)
    
    然后Canvas用grid(row=0, column=0, sticky="nsew"),这样Frame缩放时Canvas也会跟着放大缩小

如果之前你的create_window没生效,大概率是Canvas没布局或者控件父容器错了,对照上面的代码改改应该就能解决啦~

内容的提问来源于stack exchange,提问作者Hasty Basher

火山引擎 最新活动