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

Tkinter滚动画布尺寸适配问题:右侧留白如何解决?

解决Tkinter中Canvas无法适配窗口宽度、右侧留白的问题

你的问题出在Frame的布局方式和缺少Canvas尺寸变化的响应逻辑上,具体修正方案如下:

核心修改点

  • 移除无效的frame.grid(...)代码:Frame是通过canvas.create_window嵌入Canvas的,Canvas不支持用grid布局管理子组件,这行代码完全无效,还会干扰宽度自适应。
  • 给Canvas绑定<Configure>事件,动态同步Frame宽度:当窗口/Canvas尺寸变化时,强制Frame宽度和Canvas一致,消除右侧留白。
  • 优化滚动区域的更新逻辑,确保滚动功能正常。

修改后的完整代码

import tkinter as tk
import tkinter.ttk as ttk
        
def addNewCqrs():
    backEndCqrs = []
    frontEndCqrs = [[65435213245, 6543,52143, 65463543,654654, 6546354, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654],[65435213245, 6543,52143, 65463543,654654, 6546354, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654],[65435213245, 6543,52143, 65463543,654654, 6546354, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654, 654654]]
    backEndIds = []
    newCqrs = []

    for cqr in backEndCqrs:
        backEndIds.append(cqr[0])

    for cqr in frontEndCqrs:
        if cqr[0] in backEndIds:
            continue
        newCqrs.append(cqr)

    window = tk.Tk()

    canvas = tk.Canvas(window, borderwidth=0, background='blue')
    canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    # 移除无效的grid布局代码
    frame = tk.Frame(master=canvas, relief=tk.RAISED, borderwidth=1, background='red')

    scroll = ttk.Scrollbar(master=window, command = canvas.yview)
    canvas.configure(yscrollcommand=scroll.set)
    scroll.pack(side=tk.RIGHT, fill=tk.Y)

    label = ttk.Label(master=frame)
    label.pack(fill=tk.BOTH, side=tk.TOP, expand=True)

    button = ttk.Button(master=frame, text='Exit', command=window.destroy)

    if len(newCqrs) == 0:
        label.config(text="We didn't find any new CQR's")
        button.pack(fill=tk.BOTH, side=tk.TOP)
        return
        
    label.config(text="We have added the following CQR's")

    for cqr in newCqrs:
        cqrText = (f'CQR {cqr[0]}\n'
                   f'Start time:            {cqr[1]}\n'
                   f'Completion time:       {cqr[2]}\n'
                   f'Email:                 {cqr[3]}\n'
                   f'Name:                  {cqr[4]}\n'
                   f'Dealer:                {cqr[5]}\n'
                   f'Customer:              {cqr[6]}\n'
                   f'Date reported:         {cqr[7]}\n'
                   f'Order number:          {cqr[8]}\n'
                   f'Invoice number:        {cqr[9]}\n'
                   f'Serial number:         {cqr[10]}\n'
                   f'Failed part number:    {cqr[11]}\n'
                   f'Causal part number:    {cqr[12]}\n'
                   f'Part Description:      {cqr[13]}\n'
                   f'Defect observed:       {cqr[14]}\n'
                   f'Files:                 {cqr[15]}\n')

        # 这里可以把wraplength设为动态值,或者留空让标签自适应Frame宽度
        label = ttk.Label(master=frame, text=cqrText, justify=tk.LEFT)
        label.pack(fill=tk.BOTH, side=tk.TOP)

    button.pack(fill=tk.BOTH, side=tk.TOP)

    canvas.create_window((0,0), window=frame, anchor=tk.NW)
    # 给Canvas绑定尺寸变化事件,同步Frame宽度
    canvas.bind("<Configure>", lambda event, frame=frame: onCanvasConfigure(event, frame, canvas))
    # 保留Frame的配置事件更新滚动区域
    frame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))
    
def onCanvasConfigure(event, frame, canvas):
    # 让Frame宽度等于Canvas的宽度
    canvas.itemconfigure(canvas.find_withtag(frame)[0], width=event.width)
    # 更新滚动区域
    onFrameConfigure(canvas)

def onFrameConfigure(canvas):
    canvas.configure(scrollregion=canvas.bbox('all'))

addNewCqrs()

修正逻辑说明

原来的Canvas虽然能通过fill=tk.BOTH和expand=True占满窗口,但内部的Frame宽度不会自动跟随Canvas变化,导致Canvas右侧出现空白。通过监听Canvas的<Configure>事件,实时调整Frame的宽度,就能让Frame内的所有组件完全适配窗口宽度,彻底消除留白。

另外,代码中把标签的wraplength去掉了,这样标签会自动根据Frame宽度换行,比固定数值更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:55:21