首页 > 解决方案 > 避免 canvas create_window 与其他小部件重叠

问题描述

我正在 Windows 上使用 python 3.6 tkinter 制作类似扫雷的游戏。我使用了来自https://stackoverflow.com/a/47985165/8110056的代码。但是,create_window 对象在滚动时会与其他小部件重叠。我试图用框架包裹画布,但没有区别。

class Scrollable(tk.Frame):
"""
   Make a frame scrollable with scrollbar on the right.
   After adding or removing widgets to the scrollable frame, 
   call the update() method to refresh the scrollable area.
"""

def __init__(self, frame, **kwargs):
    scrollbar = tk.Scrollbar(win,)
    scrollbar.grid(row=0, column=1, sticky=tk.NS)#pack(side=tk.LEFT, fill=tk.Y, expand=True)

    w = kwargs.get('width', MAP_WIDTH)
    h = kwargs.get('height', MAP_HEIGHT)


    self.canvas = tk.Canvas(frame, yscrollcommand=scrollbar.set, height=h-100, width=w-100,  # produce 
                            highlightthickness=0, borderwidth=5, background='#123456')
    self.canvas.grid(row=2)

    scrollbar.config(command=self.canvas.yview)

    self.canvas.bind('<Configure>', self._fill_canvas)

    super().__init__(frame, **kwargs)         
    self.windows_item = self.canvas.create_window(0,0, window=self, anchor=tk.NW,)

def _fill_canvas(self, event):
    "Enlarge the windows item to the canvas width"
    canvas_width = event.width
    self.canvas.itemconfig(self.windows_item, width = canvas_width)        

def update(self):
    "Update the canvas and the scrollregion"
    self.update_idletasks()
    self.canvas.config(scrollregion=self.canvas.bbox(tk.ALL))

win = tk.Tk()
MAP_WIDTH = 25*columns
MAP_HEIGHT = 25*rows
whole_frame = tk.Frame(win, relief=tk.RIDGE, borderwidth=10, )
whole_frame.grid(row=0, column=0)
top_frame = tk.Frame(whole_frame, width=MAP_WIDTH, padx=10)
top_frame.grid(sticky=tk.EW)
divider = tk.Frame(whole_frame, relief=tk.RAISED,
                   height=10, width=MAP_WIDTH, borderwidth=10)
divider.grid(row=1)
bottom_frame = Scrollable(whole_frame,)


realmap = [tk.Button(...) for i in range(rows*columns)]
for i in realmap:
    i.grid(...)

bottom_frame.update()
win.update()

https://i.stack.imgur.com/Frzjn.gif

标签: python-3.xtkintertkinter-canvas

解决方案


可以通过将按钮的父级从 button_frame 更改为 self.canvas 来简单地解决此问题。 super().__init__(frame, **kwargs)super().__init__(self.canvas, **kwargs)


推荐阅读