【问题标题】:How to get an all sticky grid of Treeview and Scrollbar in Python Tkinter?如何在 Python Tkinter 中获得 Treeview 和 Scrollbar 的所有粘性网格?
【发布时间】:2016-09-26 15:50:38
【问题描述】:

我在 Python 2.7 中的 Tkinter 中想要的是以下网格布局:

但是有一次,我开始使用 grid() 函数而不是 pack() 函数,运行脚本时没有显示任何内容。以下是我坚持的:

import Tkinter, ttk

class App(Tkinter.Frame):
    def __init__(self,parent):
        Tkinter.Frame.__init__(self, parent, relief=Tkinter.SUNKEN, bd=2)
        self.parent = parent        
        self.grid(row=0, column=0, sticky="nsew")
        self.menubar = Tkinter.Menu(self)
        try:
            self.parent.config(menu=self.menubar)
        except AttributeError:
            self.tk.call(self.parent, "config", "-menu", self.menubar)    

        self.tree = ttk.Treeview(self.parent)
        self.tree.grid(row=0, column=0, sticky="nsew")

        self.yscrollbar = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
        self.yscrollbar.grid(row=0, column=1, sticky='nse')
        self.tree.configure(yscrollcommand=self.yscrollbar.set)
        self.yscrollbar.configure(command=self.tree.yview)

if __name__ == "__main__":
    root = Tkinter.Tk()
    root.title("MyApp")
    app = App(root)
    app.pack()
    app.mainloop()

我们将不胜感激。

【问题讨论】:

    标签: python python-2.7 tkinter treeview


    【解决方案1】:

    您有几个问题正在影响您的布局。

    首先,App 内部的一些小部件使用self 作为父级,一些使用self.parent。在这种特殊情况下,他们都应该使用self。因此,首先要做的是将Treeview 的父选项更改为self

    self.tree = ttk.Treeview(self)
    

    第二,由于你的主代码调用app.pack(),你不应该调用self.grid。删除行 `self.grid(row=0, column=0, sticky="nsew")。这是多余的。

    第三,您使用非常不寻常的代码来添加菜单栏。您需要配置根窗口的菜单。没有必要把它放在try/except 块中,也没有理由使用self.tk.call。只需这样做:

    self.parent.configure(menu=self.menubar)
    

    这假定self.parent 确实是根窗口。如果您不想强制执行该假设,可以使用winfo_toplevel(),它将始终返回最顶层的窗口:

    self.parent.winfo_toplevel().configure(menu=self.menubar)
    

    最后,由于您使用的是grid,您需要为至少一行和一列赋予“权重”,以便 tkinter 知道如何分配额外空间(例如当用户调整窗口大小时)。

    在您的情况下,您希望将所有权重赋予第 0 行和第 0 列(零),因为这是您放置需要最多空间的小部件的位置:

    def __init__(self, parent):
        ...
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
    

    注意:您还需要确保在调用app.pack() 时为其提供参数,使其也填充任何额外的空间。否则树会填满“app”,但“app”不会填满窗口。

    app.pack(fill="both", expand=True)
    

    这是一个包含所有这些更改的完整示例。我将主要布局代码组合在一起,因为这使代码更易于可视化且更易于维护:

    import Tkinter, ttk
    
    class App(Tkinter.Frame):
        def __init__(self,parent):
            Tkinter.Frame.__init__(self, parent, relief=Tkinter.SUNKEN, bd=2)
            self.parent = parent        
    
            self.menubar = Tkinter.Menu(self)
            self.parent.winfo_toplevel().configure(menu=self.menubar)
    
            self.tree = ttk.Treeview(self)
    
            self.yscrollbar = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
            self.tree.configure(yscrollcommand=self.yscrollbar.set)
    
            self.tree.grid(row=0, column=0, sticky="nsew")
            self.yscrollbar.grid(row=0, column=1, sticky='nse')
            self.yscrollbar.configure(command=self.tree.yview)
    
            self.grid_rowconfigure(0, weight=1)
            self.grid_columnconfigure(0, weight=1)
    
    if __name__ == "__main__":
        root = Tkinter.Tk()
        root.title("MyApp")
        app = App(root)
        app.pack(fill="both", expand=True)
        app.mainloop()
    

    您的问题提到了网格,但在这种情况下,您可以使用pack 节省几行代码。 pack 在这样的布局中表现出色,您的 gui 从上到下和/或从左到右对齐。您需要做的就是用这两行替换最后五行(对grid、grid_rowconfigureandgrid_columnconfigure 的调用):

    self.yscrollbar.pack(side="right", fill="y")
    self.tree.pack(side="left", fill="both", expand=True)
    

    【讨论】:

    • 太棒了!我看到滚动条穿过菜单栏的楼层直到窗口区域的顶部。可以解决吗?
    • @smlq:这不是你看到的。菜单栏是不可见的,因为您没有在其中放置任何内容。您认为的菜单栏实际上是树视图的标题。菜单栏将始终扩展窗口的整个宽度。
    • 糟糕!我的错!谢谢!嘿嘿!事实上,我只使用pack()。在这个特定的布局中它更干净。
    猜你喜欢
    • 2020-10-18
    • 2013-03-09
    • 2020-12-01
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    • 2021-10-01
    • 2019-06-08
    • 1970-01-01
    相关资源
    最近更新 更多