框架在 tkinter 中没有堆叠在一起 [英] Frames not stacking on top of each other in tkinter

查看:28
本文介绍了框架在 tkinter 中没有堆叠在一起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 tkinter 中将页面"堆叠在一起时遇到问题.

I have a problem stacking 'Pages' on top of each other in tkinter.

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

I have a main Frame that contains two sub frames which both contain different information. The first sub frame contains a Listbox and a couple buttons and is packed to the left in the main Frame. The 2nd frame is supposed to conain different 'Pages' (two for now) and have them fill up the entire frame. My issue is that both 'Pages' are displayed side by side instead of on top of each other.

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)

如果我取消注释这两行.我收到一条错误消息,提示我无法在内部使用几何管理器网格.

if I uncoment these two lines. I get an error saying I cannot use geometry manager grid inside.

        # 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() 以避免将来可能意外地将值输入到隐藏的输入框中.

Both 'Pages' are initialized and displayed at the same time which makes sense. I just don't know how to make one rise over the other since frame.tkraise() supposed to be doing this but is not. I would also like to be able to do grid_forget() on the page or pages that are not on top to avoid potentially accidentally enter values into a hidden entrybox in the future.

如果我注释掉未来"页面,那么常规"页面将占用整个框架空间,因此使用 grid_forget() 我会产生相同的结果.我只是不知道我会在哪里,但是 grid_forget() 然后我还会在哪里重新配置或执行 grid() 调用?

If I comment out the 'Future' page then the 'General' page will take up the whole frame space so with grid_forget() I would yield the same result. I just don't know where I would but grid_forget() and then also where would I re-configure or do a grid() call?

推荐答案

我的问题是两个页面"并排显示,而不是彼此重叠显示.

My issue is that both 'Pages' are displayed side by side instead of on top of each other.

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

If you use pack() to place a frame on your root window and then use grid() inside of that frame then it will work but if you try to use pack() inside of a frame and then try to use grid() inside of that same frame it will fail.

对于根窗口和框架也是如此.如果 pack() 在根窗口中有一个框架,那么您不能使用 grid() 将任何内容放入同一个根窗口中.

The same goes for the root window and frames. If pack() a frame in the root window then you cannot use grid() to place anything into that same root window.

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

The problem with the grid() vs pack() issue was because the location where the class General and class Future was configuring the label widgets was the parent frame where pack() was being used. This prevented the use of grid() in that same parent frame to place the General and Future frames.

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

To fix this we change:

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')

以上是使其正常工作所需的唯一修复.

the above was the only fix needed for this to work properly.

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")

        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)

        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(self, 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(self, text='Future')
        label.pack(side='left', fill='both', expand=True)
        print("Hi I'm Future")

app = Settings()
app.mainloop()

这篇关于框架在 tkinter 中没有堆叠在一起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆