
在tkinter中,所有可视化组件(widget)都必须有一个父容器。这个父容器决定了组件在界面层级中的位置,并影响其布局行为。当我们创建一个自定义的tkinter组件类时,尤其是在继承现有组件(如ttk.treeview)时,正确地将父容器传递给基类的构造函数至关重要。
考虑以下一个自定义的myTree类,它继承自ttk.Treeview:
from tkinter import *
from tkinter import ttk
class myTree(ttk.Treeview):
    def __init__(self, parent, width, *args):
        # 初始实现:未将 parent 传递给基类构造函数
        super().__init__() 
        self['show'] = 'headings'
        self['columns'] = args
        for column in args:
            self.column(column, anchor=CENTER, width=width)
            self.heading(column, text=column, anchor=CENTER)
# 主程序中创建和布局
main = Tk()
frame1 = Frame(main)
frame1.pack()
test = myTree(frame1, 100, 'A', 'B', 'C', 'D', 'E')
# 添加垂直滚动条
scrollbarV = ttk.Scrollbar(frame1, orient=VERTICAL, command=test.yview)
scrollbarV.pack(side='right', fill='y')
test.config(yscroll=scrollbarV.set)
# 添加水平滚动条
scrollbarH = ttk.Scrollbar(frame1, orient=HORIZONTAL, command=test.xview)
scrollbarH.pack(side='bottom', fill='x')
test.config(xscroll=scrollbarH.set)
test.pack() # Treeview被打包
main.mainloop()上述代码中,尽管myTree类的__init__方法接收了parent参数,但在调用super().__init__()时,这个parent参数并未被传递给ttk.Treeview的构造函数。这意味着test这个myTree实例实际上并没有被创建为frame1的子组件,而是默认成为了根窗口main的子组件。
当test.pack()被调用时,由于test是main的子组件,它会被打包在main窗口的层级中。而frame1及其内部的滚动条则在main窗口的另一个层级中。在frame1.pack()之后,test.pack()会将test放置在frame1的下方(默认的pack行为),导致滚动条看起来位于Treeview的上方。
解决这个问题的关键在于确保myTree实例正确地将其父容器parent传递给ttk.Treeview的构造函数。
class myTree(ttk.Treeview):
    def __init__(self, parent, width, *args):
        # 修正:将 parent 传递给基类构造函数
        super().__init__(parent)  # 关键修正
        self['show'] = 'headings'
        self['columns'] = args
        for column in args:
            self.column(column, anchor=CENTER, width=width)
            self.heading(column, text=column, anchor=CENTER)通过这一修正,test实例现在正确地成为了frame1的子组件。当test.pack()被调用时,它会在frame1内部进行布局,与同样打包在frame1内部的滚动条协同工作,从而实现预期的布局效果。
除了修正父容器问题,为了使Treeview组件能够更好地响应窗口大小变化并充分利用可用空间,我们通常会结合pack()方法的fill和expand选项。
将这些选项应用于test.pack()调用,可以进一步优化布局:
test.pack(fill="both", expand=1) # 修正后的打包方式
以下是整合了所有修正和优化后的完整代码:
from tkinter import *
from tkinter import ttk
class myTree(ttk.Treeview):
    def __init__(self, parent, width, *args):
        # 关键修正:将 parent 传递给基类构造函数
        super().__init__(parent) 
        self['show'] = 'headings'
        self['columns'] = args
        for column in args:
            self.column(column, anchor=CENTER, width=width)
            self.heading(column, text=column, anchor=CENTER)
main = Tk()
main.title("Tkinter自定义Treeview与滚动条示例")
# 创建一个Frame作为Treeview和滚动条的容器
frame1 = Frame(main)
frame1.pack(fill="both", expand=1) # 让frame1也填充并扩展
test = myTree(frame1, 100, 'A', 'B', 'C', 'D', 'E')
# 添加垂直滚动条
scrollbarV = ttk.Scrollbar(frame1, orient=VERTICAL, command=test.yview)
scrollbarV.pack(side='right', fill='y')
test.config(yscrollcommand=scrollbarV.set) # 使用 yscrollcommand
# 添加水平滚动条
scrollbarH = ttk.Scrollbar(frame1, orient=HORIZONTAL, command=test.xview)
scrollbarH.pack(side='bottom', fill='x')
test.config(xscrollcommand=scrollbarH.set) # 使用 xscrollcommand
# 将Treeview打包在frame1内部,并使其填充和扩展
test.pack(side='left', fill="both", expand=1) # 调整Treeview的打包方式
main.mainloop()注意: Treeview的yscroll和xscroll配置项在较新版本的Tkinter中应为yscrollcommand和xscrollcommand,用于指定滚动条的set方法。
通过遵循这些原则,开发者可以有效地创建功能完善且布局正确的自定义Tkinter组件,避免常见的布局陷阱。
以上就是Tkinter自定义Treeview与滚动条的正确集成方法的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号