框架在tkinter中没有堆叠在彼此之上

时间:2017-07-26 14:22:58

标签: python tkinter

我在堆叠' Pages'在tkinter中彼此重叠。

我有一个主Frame,它包含两个包含不同信息的子帧。第一个子帧包含Listbox和几个按钮,并在主框架的左侧打包。第二帧应该具有不同的“页面”。 (现在两个)并让它们填满整个框架。 我的问题是这两个页面都是'并排显示而不是彼此重叠。

import tkinter as tk


class Settings(tk.Tk):

    def __init__(self, master=None):
        tk.Tk.__init__(self, master)
        self.focus_force()
        self.grab_set()
        # set focus to settings window
        # Main window title
        self.title("Settings")


        # set up grid containers
        container_main = tk.Frame(self, width=500, height=700)
        container_main.pack(side='top', fill='both', expand=True)
        container_main.grid_rowconfigure(0, weight=1)
        container_main.grid_columnconfigure(0, weight=1)

        container_listbox = tk.Frame(container_main, bg='blue', width=200, height=700)
        container_listbox.pack(side='left', fill='both', expand=True)
        container_listbox.grid_rowconfigure(0, weight=1)
        container_listbox.grid_columnconfigure(0, weight=1)

        container_settings = tk.Frame(container_main, bg='red', width=300, height=700)
        container_settings.pack(side='right', fill='both', expand=True)
        container_settings.grid_rowconfigure(0, weight=1)
        container_settings.grid_columnconfigure(0, weight=1)

        # build settings pages
        self.frames = {}

        self.frames["Options"] = Options(parent=container_listbox, controller=self)
        self.frames["General"] = General(parent=container_settings, controller=self)
        self.frames["Future"] = Future(parent=container_settings, controller=self)

如果我解开这两行。我得到一个错误,说我不能在里面使用几何管理器网格。

        # self.frames["General"].grid(row=0, column=0, sticky='nsew')
        # self.frames["Future"].grid(row=0, column=0, sticky='nsew')

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


class Options(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(parent, text='List Box')
        label.grid(row=0, column=0, sticky='nsew', padx=1, pady=1)
        button1 = tk.Button(parent, text='General', command=lambda: controller.show_frame('General'))
        button2 = tk.Button(parent, text='Future', command=lambda: controller.show_frame('Future'))
        button1.grid(row=1, column=0, sticky='ew')
        button2.grid(row=2, column=0, sticky='ew')


class General(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(parent, text='General')
        label.pack(side='left', fill='both', expand=True, )
        print("Hi I'm General")

class Future(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(parent, text='Future')
        label.pack(side='left', fill='both', expand=True)
        print("Hi I'm Future")

app = Settings()
app.mainloop()

两个页面'在有意义的同时进行初始化和显示。我只是不知道如何让一个人在另一个上升,因为frame.tkraise()应该这样做,但事实并非如此。我还希望能够在不在顶部的页面上执行grid_forget(),以避免将来可能意外地将值输入隐藏的输入框。

编辑:如果我评论出未来'页面然后是' General'页面将占用整个框架空间,因此使用grid_forget()我会得到相同的结果。我只是不知道我会在哪里grid_forget(),然后我还会在哪里重新配置或进行grid()来电?

2 个答案:

答案 0 :(得分:2)

  

我的问题是这两个页面都是'并排显示而不是彼此重叠。

如果您使用pack()在根窗口上放置一个框架,然后在该框架内使用grid(),那么它会起作用,但如果您尝试在框架内使用pack()然后尝试在同一帧内使用grid(),它将失败。

根窗口和框架也是如此。如果pack()根窗口中有一个框架,则您无法使用grid()将任何内容放入同一个根窗口。

grid() vs pack()问题的问题是因为类General和类Future配置标签小部件的位置是父框架{{{正在使用1}}。这阻止了在同一父框架中使用pack()来放置General和Future框架。

为了解决这个问题,我们改变了:

grid()

为:

label = tk.Label(parent, text='General')

and

label = tk.Label(parent, text='Future')

以上是唯一可以正常工作的修复方法。

label = tk.Label(self, text='General')

and

label = tk.Label(self, text='Future')

答案 1 :(得分:2)

我冒昧地重组您的应用程序逻辑,以表达如何更容易解决您的问题 - 我还提供了一些其他信息。

您当前实施的问题是hideshow您的网页的问题,在您的按钮的command关键字分配中。在我提供的实现中,Options类是所有魔法发生的地方 - 特别是show_generalshow_future方法。简单地说,当点击常规按钮时,我在pack_forget()窗口小部件上调用future_page,在pack(...)窗口小部件上调用general_page,反之亦然,当我想要显示未来页面时。 (这可以很容易地实现,但我会把它留给你。)

此外,我以模块化代码的方式构建应用程序逻辑,因此在每个步骤中我都可以测试它,看看我在哪里,例如我开始在main()创建每个容器,并确保所有内容都正确布局(我喜欢给每个容器一个不同的颜色,使其更容易可视化间距等),然后再转到{{1我将放置小部件的框架和Settings框架,并编写GUI按预期运行所需的代码。

我不会解释每一行,但我确信在这一点上你可以看到我所得到的。我建议阅读代码(从Options开始), 并弄清楚我是如何以及为什么以我的方式写这个。 (我把它写成了我认为你想要的功能,以及在这里和那里提供一些指示 - 它并不意味着完美。)

main()

我希望这有帮助!