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

CustomTkinter可滚动框架无法完全滚到底部问题求助

CustomTkinter聊天应用滚动到底部失效问题

问题描述

使用Tkinter + CustomTkinter开发聊天应用,点击按钮添加消息元素后,调用frameChat._parent_canvas.yview_moveto(1)试图滚动到最新消息,但仅能滚动一部分,无法完全滚到底部。

问题代码

import customtkinter
from customtkinter import *
import tkinter
from PIL import Image

customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("blue.json")

root = tkinter.Tk()

root.title("🍕 PizzBot")
root.geometry("455x771")
root.resizable(False, False)
root.configure(background="#2C2C2C")
send = Image.open("send.png")
head = Image.open("ChatBot CanvaDesign.png")
pizzaIco = Image.open("pizza.png")
usr = Image.open("user.png")

framePrompt = customtkinter.CTkFrame(root)
framePrompt.pack(side=BOTTOM)
frameChat = customtkinter.CTkScrollableFrame(root, width=430,height=650)
frameChat.pack()

prompt_input = customtkinter.CTkEntry(framePrompt,height=55,width=375,border_width=0,placeholder_text="Type your prompt here",placeholder_text_color=("gray95", "grey"),font=("Poppins", 18),)
prompt_input.grid(column=0, row=0, padx=6, pady=8)
def executeSend():
    customtkinter.CTkLabel(frameChat,text="\n").pack()

    label = customtkinter.CTkLabel(frameChat,text=prompt_input.get(),font=("Poppins", 20,"bold"),anchor="w",width=20,height=35,wraplength="300",justify="left",padx=20,pady=20,text_color="white",fg_color="#3f52ff",corner_radius=20)
    frameChat.configure(width=430,height=700)
    label.pack(anchor="e",padx=10)

    customtkinter.CTkLabel(frameChat,text="\n").pack()

    promptReply = customtkinter.CTkLabel(frameChat,text="Bot Response Goes Here . Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi urna magna, ultrices sit amet auctor sit amet, facilisis in enim. Etiam leo nunc, vulputate vitae sem eu, vehicula laoreet purus. Nam vulputate et lacus vel iaculis. Pellentesque vel eros dui. Quisque consectetur sed felis sed lacinia.",fg_color="white",text_color="#3F52FF",padx=20,pady=20,wraplength="300",justify="left",anchor="w",font=("Quicksand",18),corner_radius=10,)
    promptReply.pack(anchor="w",padx=10)

    frameChat.configure(height=600)

    root.after(100,frameChat._parent_canvas.yview_moveto(1))#Code To Move The Scrollbar Down

    customtkinter.CTkFrame(frameChat,fg_color="#2C2C2C",width=410,height=15).pack()
    customtkinter.CTkFrame(frameChat,fg_color="#3F52FF",width=10,height=5).pack()
    customtkinter.CTkLabel(frameChat,text="\n").pack()

btnSend = customtkinter.CTkButton(framePrompt,text="",corner_radius=10,image=CTkImage(light_image=send, dark_image=send),width=55,height=55,command=executeSend)
btnSend.grid(column=1, row=0)

prompt_input.bind("<Return>", lambda event: executeSend())

root.mainloop()

问题原因及修复方案

1. after方法调用错误

当前写法root.after(100, frameChat._parent_canvas.yview_moveto(1))会立即执行yview_moveto(1),而非等待100毫秒后执行。after的第二个参数需传入函数对象,而非函数调用结果。

修复:将调用包装为lambda函数:

root.after(100, lambda: frameChat._parent_canvas.yview_moveto(1))

2. 元素添加顺序错误

滚动代码执行后仍在向frameChat添加新元素,这些元素会改变滚动区域大小,但滚动操作已完成,导致最终位置不是真正的底部。

修复:将所有元素添加完成后再执行滚动操作,把滚动代码移到所有pack()操作之后。

3. 不必要的框架高度修改

代码中反复修改frameChat的高度,会干扰滚动区域计算,建议移除这两行无关配置:

frameChat.configure(width=430,height=700)
frameChat.configure(height=600)

修复后的完整代码

import customtkinter
from customtkinter import *
import tkinter
from PIL import Image

customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("blue.json")

root = tkinter.Tk()

root.title("🍕 PizzBot")
root.geometry("455x771")
root.resizable(False, False)
root.configure(background="#2C2C2C")
send = Image.open("send.png")
head = Image.open("ChatBot CanvaDesign.png")
pizzaIco = Image.open("pizza.png")
usr = Image.open("user.png")

framePrompt = customtkinter.CTkFrame(root)
framePrompt.pack(side=BOTTOM)
frameChat = customtkinter.CTkScrollableFrame(root, width=430,height=650)
frameChat.pack()

prompt_input = customtkinter.CTkEntry(framePrompt,height=55,width=375,border_width=0,placeholder_text="Type your prompt here",placeholder_text_color=("gray95", "grey"),font=("Poppins", 18),)
prompt_input.grid(column=0, row=0, padx=6, pady=8)

def executeSend():
    customtkinter.CTkLabel(frameChat,text="\n").pack()

    label = customtkinter.CTkLabel(frameChat,text=prompt_input.get(),font=("Poppins", 20,"bold"),anchor="w",width=20,height=35,wraplength="300",justify="left",padx=20,pady=20,text_color="white",fg_color="#3f52ff",corner_radius=20)
    label.pack(anchor="e",padx=10)

    customtkinter.CTkLabel(frameChat,text="\n").pack()

    promptReply = customtkinter.CTkLabel(frameChat,text="Bot Response Goes Here . Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi urna magna, ultrices sit amet auctor sit amet, facilisis in enim. Etiam leo nunc, vulputate vitae sem eu, vehicula laoreet purus. Nam vulputate et lacus vel iaculis. Pellentesque vel eros dui. Quisque consectetur sed felis sed lacinia.",fg_color="white",text_color="#3F52FF",padx=20,pady=20,wraplength="300",justify="left",anchor="w",font=("Quicksand",18),corner_radius=10,)
    promptReply.pack(anchor="w",padx=10)

    # 添加底部分隔元素
    customtkinter.CTkFrame(frameChat,fg_color="#2C2C2C",width=410,height=15).pack()
    customtkinter.CTkFrame(frameChat,fg_color="#3F52FF",width=10,height=5).pack()
    customtkinter.CTkLabel(frameChat,text="\n").pack()

    # 最后执行滚动,确保所有元素都已添加完毕
    root.after(100, lambda: frameChat._parent_canvas.yview_moveto(1))

btnSend = customtkinter.CTkButton(framePrompt,text="",corner_radius=10,image=CTkImage(light_image=send, dark_image=send),width=55,height=55,command=executeSend)
btnSend.grid(column=1, row=0)

prompt_input.bind("<Return>", lambda event: executeSend())

root.mainloop()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:52:32