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

CustomTkinter:左侧固定框架旁实现可垂直滚动框架布局问题

CustomTkinter混合滚动布局与滚动条绑定问题

原始布局问题:右侧垂直滚动框无法占满剩余水平空间

问题描述

基于CustomTkinter开发的应用包含一个水平方向的CTkScrollableFrame,内部有两个子框架:

  • 左侧不可滚动的蓝色CTkFrame,内含蓝绿色子框架
  • 右侧垂直方向的红色CTkScrollableFrame,内含橙色和黄色子框架

目前水平滚动框已充满窗口,但右侧垂直滚动框无法占据剩余全部水平空间。

解决方案(修改OLD MWE)

核心问题是未正确配置CTkScrollableFrame内部的网格权重,改用grid布局替代pack能更精准控制空间分配:

from customtkinter import CTkFrame, CTk, CTkScrollableFrame

root = CTk()
root.geometry("800x500")

# 水平滚动框架
h_scroll_frame = CTkScrollableFrame(root, orientation="horizontal")
h_scroll_frame.pack(fill="both", expand=True)
# 配置水平滚动框架内部的列权重:第0列固定宽度,第1列占剩余空间
h_scroll_frame.grid_columnconfigure(0, weight=0)
h_scroll_frame.grid_columnconfigure(1, weight=1)
h_scroll_frame.grid_rowconfigure(0, weight=1)

# 左侧不可滚动蓝色框架
left_frame = CTkFrame(h_scroll_frame, fg_color="blue")
left_frame.grid(column=0, row=0, sticky="nsew", padx=2, pady=2)
left_frame.grid_rowconfigure(0, weight=1)
left_frame.grid_columnconfigure(0, weight=1)
# 内部蓝绿色子框架
CTkFrame(left_frame, fg_color="teal", border_color="black", border_width=3).grid(column=0, row=0, sticky="nsew", padx=10, pady=10)

# 右侧垂直滚动红色框架
v_scroll_frame = CTkScrollableFrame(h_scroll_frame, fg_color="red")
v_scroll_frame.grid(column=1, row=0, sticky="nsew", padx=2, pady=2)
# 配置垂直滚动框架内部的列权重,让子框架能扩展
v_scroll_frame.grid_columnconfigure(0, weight=1)
v_scroll_frame.grid_columnconfigure(1, weight=1)
v_scroll_frame.grid_rowconfigure(0, weight=1)

# 内部橙色、黄色子框架
orange_frame = CTkFrame(v_scroll_frame, fg_color="orange", border_color="black", border_width=3)
orange_frame.grid(column=0, row=0, sticky="nsew", padx=10, pady=10)
yellow_frame = CTkFrame(v_scroll_frame, fg_color="yellow", border_color="black", border_width=3)
yellow_frame.grid(column=1, row=0, sticky="nsew", padx=10, pady=10)

root.mainloop()

修改说明

  1. 给水平滚动框架h_scroll_frame配置列权重:第0列(左侧框架)固定,第1列(右侧滚动框)占满剩余空间
  2. 所有子框架使用grid布局并设置sticky="nsew",确保填充父容器
  3. 为每个父框架配置内部的行/列权重,让子组件能随窗口大小变化自动扩展

补充问题:垂直滚动条无法控制canvas_v滚动(NEW MWE)

问题描述

改用Canvas实现滚动框架后,垂直滚动条无法控制右侧的canvas_v,需要修复滚动绑定与布局配置。

解决方案(修改NEW MWE)

from customtkinter import CTk, CTkFrame, CTkScrollbar
from tkinter import Canvas

def scroll_x(*args):
    """水平滚动回调"""
    canvas_h.xview(*args)

def scroll_y(*args):
    """垂直滚动回调"""
    canvas_v.yview(*args)
    
def handle_mousewheel(event):
    """鼠标滚轮垂直滚动"""
    canvas_v.yview_scroll(int(-1*(event.delta/120)), "units")
    
def handle_mousewheel_shift(event):
    """Shift+鼠标滚轮水平滚动"""
    canvas_h.xview_scroll(int(-1*(event.delta/120)), "units")
    
def update_scrollregion(event, canvas):
    """更新滚动区域"""
    canvas.config(scrollregion=canvas.bbox("all"))
    
root = CTk()
root.geometry("800x500")

frame_h = CTkFrame(root, fg_color="blue")
frame_h.grid(column=0, row=0, sticky='nsew')

# 水平滚动条
hsb = CTkScrollbar(root, orientation='horizontal', command=scroll_x)
hsb.grid(column=0, row=1, sticky='ew')

# 根窗口布局配置
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)

# 水平滚动Canvas
canvas_h = Canvas(frame_h, highlightthickness=0)
frame_canvas_h = CTkFrame(canvas_h, fg_color="cyan")
canvas_h.config(xscrollcommand=hsb.set)
canvas_h.pack(fill='both', side='left', expand=True)
canvas_h.create_window(0, 0, window=frame_canvas_h, anchor='nw')
# 配置水平滚动内部框架的列权重:第0列固定,第1列占满剩余空间
frame_canvas_h.grid_columnconfigure(0, weight=0)
frame_canvas_h.grid_columnconfigure(1, weight=1)
frame_canvas_h.grid_rowconfigure(0, weight=1)

# 左侧蓝绿色框架
left_frame = CTkFrame(frame_canvas_h, fg_color="teal")
left_frame.grid(column=0, row=0, sticky="nsew", padx=2, pady=2)

##### 垂直滚动框架部分
frame_v = CTkFrame(frame_canvas_h, fg_color="red")
frame_v.grid(column=1, row=0, sticky="nswe", padx=2, pady=2)
# 配置垂直滚动容器的布局权重
frame_v.grid_columnconfigure(0, weight=1)
frame_v.grid_rowconfigure(0, weight=1)

# 垂直滚动条
vsb = CTkScrollbar(root, orientation='vertical', command=scroll_y)
vsb.grid(column=1, row=0, rowspan=2, sticky='ns')

# 垂直滚动Canvas
canvas_v = Canvas(frame_v, highlightthickness=0)
frame_canvas_v = CTkFrame(canvas_v, fg_color="pink")
canvas_v.config(yscrollcommand=vsb.set)
canvas_v.pack(fill='both', side='left', expand=True)
canvas_v.create_window(0, 0, window=frame_canvas_v, anchor='nw')
# 配置垂直滚动内部框架的列权重
frame_canvas_v.grid_columnconfigure(0, weight=1)
frame_canvas_v.grid_columnconfigure(1, weight=1)
frame_canvas_v.grid_rowconfigure(0, weight=1)

# 内部橙色、黄色框架
orange_frame = CTkFrame(frame_canvas_v, fg_color="orange")
orange_frame.grid(column=0, row=0, sticky="nsew", padx=10, pady=10)
yellow_frame = CTkFrame(frame_canvas_v, fg_color="yellow")
yellow_frame.grid(column=1, row=0, sticky="nsew", padx=10, pady=10)

# 绑定滚动区域更新事件
frame_canvas_h.bind("<Configure>", lambda e: update_scrollregion(e, canvas_h))
frame_canvas_v.bind("<Configure>", lambda e: update_scrollregion(e, canvas_v))

# 绑定鼠标滚轮事件
root.bind("<MouseWheel>", handle_mousewheel)
root.bind("<Shift-MouseWheel>", handle_mousewheel_shift)

root.mainloop()

修改说明

  1. 为frame_canvas_h配置列权重,让右侧frame_v占满剩余水平空间
  2. 为frame_v配置内部布局权重,确保canvas_v填充整个容器
  3. 修复垂直滚动条的sticky属性为ns(原代码写的ew,垂直滚动条应上下粘住)
  4. 添加Configure事件绑定,自动更新Canvas的滚动区域
  5. 修正鼠标滚轮事件的event.delta获取(tkinter中滚轮值存储在delta属性)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:57:09