You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python tkinter在已有Frame中创建可滚动Frame及滚动条异常排查

解决方案

核心问题

  • 同一父容器混用grid和pack布局管理器导致布局冲突,滚动条无法正常渲染
  • 仅给Canvas绑定了尺寸变化事件,内部滚动区域内容变化时没有同步更新滚动范围
  • 主Frame的place()方法未配置参数,没有正确填充窗口

修正后代码

import tkinter as tk
from tkinter import ttk


class MyGUI(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # define variables
        GRID = 25
        X = GRID*20
        Y = GRID*15

        # create spinbox
        self.Label = tk.Label(text='Number of Shafts')
        self.Label.grid(row=0, column=0)
        self.Spinbox = tk.Spinbox(from_=0, to=10, width=3)
        self.Spinbox.grid(row=0, column=1)

        # 新增滚动容器,隔离pack和grid布局
        self.scroll_container = tk.Frame(self)
        self.scroll_container.grid(row=1, column=0, columnspan=2)

        # create scrollable frame
        self.Table = tk.Canvas(self.scroll_container, height=100, width=150, background='white',
                               highlightthickness=1, highlightbackground='black')
        self.Table.pack(side='left', fill='both', expand=True)

        self.Scrollbar = ttk.Scrollbar(self.scroll_container, orient='vertical', command=self.Table.yview)
        self.Scrollbar.pack(side='right', fill='y')

        self.Table.configure(yscrollcommand=self.Scrollbar.set)

        self.Scrollable_Frame = ttk.Frame(self.Table)
        self.Table.create_window((0, 0), window=self.Scrollable_Frame, anchor="nw")

        # 给内部滚动框架绑定尺寸变化事件,内容更新时同步滚动范围
        self.Scrollable_Frame.bind("<Configure>", lambda e: self.Table.configure(scrollregion=self.Table.bbox('all')))

        for i in range(50):
            ttk.Label(self.Scrollable_Frame, text=("Sample label %d" % i)).pack()

        # create canvas
        self.canvas = tk.Canvas(self, width=X+1, height=Y+1, background='white',
                                highlightthickness=1, highlightbackground='black')
        self.canvas.grid(row=0, column=2, rowspan=2)

        # create grid
        for i in range(0, Y, GRID):
            self.canvas.create_line(0, i, X, i, fill='gray')
        for i in range(0, X, GRID):
            self.canvas.create_line(i, 0, i, Y, fill='gray')

        # create rectangle
        x0 = GRID*3
        y0 = GRID*4
        wid = GRID
        hei = GRID
        self.create_shaft(x0, y0, wid, hei)

        # add bindings to clicks
        self._drag_data = {"x": 0, "y": 0, "item": None}
        self.canvas.tag_bind('inertia', "<ButtonPress-1>", self.drag_start)
        self.canvas.tag_bind('inertia', "<ButtonRelease-1>", self.drag_stop)
        self.canvas.tag_bind('inertia', "<B1-Motion>",
                             lambda event, grid_x=GRID, grid_y=GRID: self.drag(event, grid_x, grid_y))

    def create_shaft(self, x0, y0, wid, hei):
        """Create shaft drawing"""
        self.canvas.create_rectangle(x0, y0, x0+wid, y0+hei, fill='gray', tags=('inertia',))

    def drag_start(self, event):
        """Beginning drag of an object"""
        # record the item and its location
        self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
        self._drag_data["x"] = event.x
        self._drag_data["y"] = event.y

    def drag_stop(self, event):
        """End drag of an object"""
        # reset the drag information
        self._drag_data["item"] = None
        self._drag_data["x"] = 0
        self._drag_data["y"] = 0

    def drag(self, event, grid_x, grid_y):
        """Handle dragging of an object"""
        # compute how much the mouse has moved
        delta_x = round((event.x - self._drag_data["x"])/grid_x)*grid_x
        delta_y = round((event.y - self._drag_data["y"])/grid_y)*grid_y
        # move the object the appropriate amount
        self.canvas.move(self._drag_data["item"], delta_x, delta_y)
        # record the new position
        self._drag_data["x"] += delta_x
        self._drag_data["y"] += delta_y


if __name__ == "__main__":
    app = tk.Tk()
    app.title('hi')
    # 主Frame用pack填充整个窗口
    MyGUI(app).pack(fill=tk.BOTH, expand=True)
    app.mainloop()

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:48:02