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

求助:如何为含大量按钮的CTkFrame添加可用Scrollbar

解决CustomTkinter销售页面滚动条失效问题

问题说明

使用CustomTkinter和Tkinter开发销售页面时,点击ShowAllSales按钮会在self.AllInsideThisFrame中生成大量销售按钮,但添加滚动条后仅显示灰色不可用状态。此前已实现文本内容的可滚动框架,现需适配按钮场景,将self.AllInsideThisFrame改造为可滚动框架。

解决方案

核心问题是普通CTkFrame无法自动识别内部超出视口的内容,且使用place布局不会触发容器的高度计算。CustomTkinter提供了CTkScrollableFrame组件,专门用于处理滚动场景,只需调整布局方式即可激活滚动条:

  • 用ctk.CTkScrollableFrame替代普通CTkFrame,组件自带滚动条,无需手动配置
  • 内部按钮改用pack布局(而非place),让容器自动计算内容总高度
  • 每次点击按钮时先销毁旧的滚动框架,避免重复创建
  • 避免循环中重复创建标题标签,仅初始化一次

修改后的完整代码

class sales_page(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.config(background="#333333")

        TopOfWindowFrame = ctk.CTkFrame(self, bg_color="#333333", fg_color="grey", height=100)
        TopOfWindowFrame.pack(padx=0, pady=0, fill='x', expand=True, anchor='n')

        labelaoralogo = ctk.CTkLabel(TopOfWindowFrame, image=aoralogo, text='')
        labelaoralogo.pack(padx=5, pady=5, anchor='center', expand=True)

        # SalesPageFramesAndUI
        self.ShowOptionsFrame = ctk.CTkFrame(self, fg_color='white', bg_color='#333333', width=400, height=600)
        self.ShowOptionsFrame.pack(padx=5, pady=5, fill='y', expand=True, side='top', anchor='nw')

        ShowAllSales = ctk.CTkButton(self.ShowOptionsFrame, width=400, height=50, text='Όλες οι πωλήσεις',
                                     font=('robotic bold', 20), hover_color='#4B0082', fg_color='#a881af',
                                     command=self.AllSalesOrders,
                                     border_width=3, border_color='black')
        ShowAllSales.place(x=0, y=0)

        ShowSalesByCustomer = ctk.CTkButton(self.ShowOptionsFrame, width=400, height=50, text='Πωλήσεις ανά Πελάτη',
                                            font=('robotic bold', 20), hover_color='#4B0082', fg_color='#a881af',
                                            border_width=3, border_color='black')
        ShowSalesByCustomer.place(x=0, y=47)

        # 初始化滚动框架变量,避免重复创建时报错
        self.AllInsideThisFrame = None

    def AllSalesOrders(self):
        # 销毁旧的滚动框架(如果存在)
        if self.AllInsideThisFrame:
            self.AllInsideThisFrame.destroy()

        CallDB = aoracandlestudiodb.cursor()
        CallDB.execute('SELECT orders_id FROM sales ORDER BY _date')
        AllSales = CallDB.fetchall()

        # 替换为CTkScrollableFrame,设置滚动方向为垂直
        self.AllInsideThisFrame = ctk.CTkScrollableFrame(self, width=1000, height=750, bg_color="#333333",
                                                         border_width=8, border_color="purple", fg_color='white')
        self.AllInsideThisFrame.place(x=450, y=150)

        # 只创建一次标题标签,放在滚动框架顶部
        SalesTypeLabel = ctk.CTkLabel(self.AllInsideThisFrame, width=980, height=50, text='Όλες οι πωλήσεις',
                                      font=('arial bold', 25), text_color='black')
        SalesTypeLabel.pack(pady=(10, 20), padx=10, fill='x')

        for sale_id in AllSales:
            get_ID_str = str(sale_id)
            get_sales_ID = get_ID_str[2:-3]
            get_sales_date = get_DateOfSale(get_sales_ID)
            get_sales_price = get_TotalPriceOfSale(get_sales_ID)
            get_sales_customer = get_CustomerOfSale(get_sales_ID)
            # 传递必要参数,无需distance(pack会自动排列)
            self.MakeButtonsForSales(get_sales_date, get_sales_ID, get_sales_price, get_sales_customer)

    def MakeButtonsForSales(self, Sales_Date, Sales_ID, Sales_price, Sales_Customer):
        self.SaleButton = ctk.CTkButton(self.AllInsideThisFrame, width=980, height=50, hover_color='#4B0082', fg_color='#a881af',
                                        text=(
                                                'Ημερομηνία: ' + Sales_Date + "                      "
                                                                              "Σύνολο Παραγγελίας: " + Sales_price +
                                                "                      Πελάτης: " + Sales_Customer),
                                        command=lambda id=Sales_ID, cust=Sales_Customer, price=Sales_price, date=Sales_Date: 
                                                self.MakeLabelsForItemsInSales(id, cust, price, date),
                                        font=('Arial', 15), border_width=5, border_color='black')
        # 用pack布局,自动垂直排列,设置上下间距
        self.SaleButton.pack(pady=5, padx=10, fill='x')

关键改动说明

  1. 替换滚动容器:用CTkScrollableFrame替代普通CTkFrame,组件自动处理滚动条逻辑
  2. 优化布局方式:按钮改用pack布局,让容器自动计算总高度,触发滚动条激活
  3. 避免重复创建:每次点击按钮先销毁旧框架,防止界面叠加
  4. 标题标签优化:将标题标签移到循环外,避免重复创建
  5. Lambda参数修正:绑定命令时显式传递参数,避免循环变量引用问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 09:34:56