简体   繁体   English

在tkinter菜单中切换帧

[英]Switching between frames in tkinter menu

I've used Tkinter to create a GUI with different menu options (a similar example is produced below). 我使用Tkinter创建了一个带有不同菜单选项的GUI(下面是一个类似的例子)。 Each menu has different commands, which when clicked create a new frame. 每个菜单都有不同的命令,单击这些命令时会创建一个新框架。 Now what is happening is if I switch to a different command, the new frame stacks below the current frame instead of replacing the old one. 现在发生的事情是,如果我切换到另一个命令,新帧将堆叠在当前帧之下而不是替换旧帧。

I want to know what is the best way to move forward. 我想知道前进的最佳方式是什么。

import Tkinter as tkinter
root = tkinter.Tk()
root.minsize(400,300)
welcome = tkinter.Frame(root).grid()
label = tkinter.Label(welcome, text="Welcome to my program").grid(row=0, column=3)
button = tkinter.Button(welcome,text="Exit",command=root.destroy).grid(row=3, column=1)
def newFrame():
newFrame = tkinter.Frame(root).grid()
newFrame_name = tkinter.Label(newFrame, text="This is another frame").grid()
menu = tkinter.Menu(root)
root.config(menu=menu)
main_menu = tkinter.Menu(menu)
menu.add_cascade(label="Main Menu", menu= main_menu)
main_menu.add_command(label="New Frame", command=newFrame)
main_menu.add_command(label="Another Frame", command=newFrame)
#menu.add_command(label="Exit", command=root.destroy, menu= filemenu)
root.mainloop()

Now if I switch between New Frame and Another Frame, the windows stack up, but I want one window to replace the other. 现在,如果我在New Frame和Another Frame之间切换,窗口会叠加,但我想要一个窗口替换另一个窗口。

Any ideas? 有任何想法吗? Thanks. 谢谢。

Here is a minimal example of one method I used recently; 这是我最近使用的一种方法的最小例子; the key is in PythonGUI.show_frame , which moves the appropriate frame to the front for display. 关键是在PythonGUI.show_frame ,它将适当的帧移动到前面以供显示。

import Tkinter as tk

class BaseFrame(tk.Frame):
    """An abstract base class for the frames that sit inside PythonGUI.

    Args:
      master (tk.Frame): The parent widget.
      controller (PythonGUI): The controlling Tk object.

    Attributes:
      controller (PythonGUI): The controlling Tk object.

    """

    def __init__(self, master, controller):
        tk.Frame.__init__(self, master)
        self.controller = controller
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        """Create the widgets for the frame."""
        raise NotImplementedError


class ExecuteFrame(BaseFrame):
    """The application home page.

    Attributes:
      new_button (tk.Button): The button to switch to HomeFrame.

    """

    def create_widgets(self):
        """Create the base widgets for the frame."""
        self.new_button = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(HomeFrame),
                                    padx=5,
                                    pady=5,
                                    text="Home")
        self.new_button.grid(padx=5, pady=5, sticky=tk.W+tk.E)


class HomeFrame(BaseFrame):
    """The application home page.

    Attributes:
      new_button (tk.Button): The button to switch to ExecuteFrame.

    """

    def create_widgets(self):
        """Create the base widgets for the frame."""
        self.new_button = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(ExecuteFrame),
                                    padx=5,
                                    pady=5,
                                    text="Execute")
        self.new_button.grid(padx=5, pady=5, sticky=tk.W+tk.E)


class PythonGUI(tk.Tk):
    """The main window of the GUI.

    Attributes:
      container (tk.Frame): The frame container for the sub-frames.
      frames (dict of tk.Frame): The available sub-frames.

    """

    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Python GUI")
        self.create_widgets()
        self.resizable(0, 0)

    def create_widgets(self):
        """Create the widgets for the frame."""             
        #   Frame Container
        self.container = tk.Frame(self)
        self.container.grid(row=0, column=0, sticky=tk.W+tk.E)

        #   Frames
        self.frames = {}
        for f in (HomeFrame, ExecuteFrame): # defined subclasses of BaseFrame
            frame = f(self.container, self)
            frame.grid(row=2, column=2, sticky=tk.NW+tk.SE)
            self.frames[f] = frame
        self.show_frame(HomeFrame)

    def show_frame(self, cls):
        """Show the specified frame.

        Args:
          cls (tk.Frame): The class of the frame to show. 

        """
        self.frames[cls].tkraise()

if __name__ == "__main__":
    app = PythonGUI()
    app.mainloop()
    exit()

There are two basic ways to solve the problem: 解决问题有两种基本方法:

  1. stack all of the frames on top of each other (eg: put in the same grid cell, or use place with the same options) and then raise the one that should be visible to the top of the stack (using frame.lift() ). 堆栈的所有帧对彼此的顶部(如:放于同一网格单元,或者使用place使用相同的选项),然后提高一个应该(使用可堆栈的顶部可见frame.lift() )。 An example of the technique is in this answer: Switch between two frames in tkinter 该答案的一个例子就是: 在tkinter中的两个帧之间切换

  2. Whenever you show a new frame, destroy (with .destroy() or hide (with pack_forget or grid_forget ) the old frame. 无论何时显示新帧, .destroy()销毁(使用.destroy()或隐藏(使用pack_forgetgrid_forget )旧帧。

I have a simple example. 我有一个简单的例子。 I'm sorry, because I don't know how to do this code by class . 对不起,因为我不知道怎么按class来做这个代码。 I just using simple code. 我只是使用简单的代码。 But it's works! 但它的确有效! :D Here it is: :D这是:

from Tkinter import *
def gantihal(frame):
    frame.tkraise()

root = Tk()

f1 = Frame(root)
f2 = Frame(root)
f3 = Frame(root)
f4 = Frame(root)
for frame in (f1, f2, f3, f4):
    frame.grid(row=0, column=0, sticky='news')

Button(f1, text='goto frame 2', command=lambda:gantihal(f2)).pack()
Label(f1, text='this is in frame 1').pack()

Label(f2, text='this is in frame two').pack()
Button(f2, text='goto frame 3', command=lambda:gantihal(f3)).pack()

Label(f3, text='this is in frame 3').pack(side='left')
Button(f3, text='next frame :)', command=lambda:gantihal(f4)).pack(side='left')

Label(f4, text='fourth frame').pack()
Button(f4, text='goto 1st frame', command=lambda:gantihal(f1)).pack()

gantihal(f1)
root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM