如何在Python Tkinter中获得Treeview和Scrollbar的全粘网格?

时间:2016-09-26 15:50:38

标签: python python-2.7 tkinter treeview

我想在Python 2.7中的Tkinter中使用以下网格布局:

Grid Layout

但是,有一次,我开始使用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()

任何帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:2)

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

首先,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知道如何分配额外空间(例如,当用户调整窗口大小时)。 / p>

在您的情况下,您希望将所有权重赋予行和列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_rowconfigure and grid_columnconfigure`):

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