【问题标题】:Switching between frames in tkinter menu在 tkinter 菜单中的帧之间切换
【发布时间】:2014-10-06 09:38:10
【问题描述】:

我使用 Tkinter 创建了一个带有不同菜单选项的 GUI(类似的示例如下所示)。每个菜单都有不同的命令,单击时会创建一个新框架。现在发生的情况是,如果我切换到不同的命令,新帧会堆叠在当前帧下方,而不是替换旧帧。

我想知道前进的最佳方式是什么。

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

现在,如果我在新框架和另一个框架之间切换,窗口会堆叠起来,但我希望一个窗口替换另一个。

有什么想法吗?谢谢。

【问题讨论】:

  • 您的代码充满了错误。缩进关闭,并且有错别字和其他错误。例如,您在 Generator 中引用了 Frame1,但 Frame1 未定义。还有一堆似乎与问题无关的代码。
  • 所有这些动态创建的框架是否都相同,或者它们是否都有自定义内容?
  • @BryanOakley 这是一个非常示例的内容。请不要查看缩进或其他错误。问题是我不可能分享确切的代码。所以我所做的就是让我知道我在做什么。问题是 - 当我从一个菜单点击到另一个菜单而不堆叠框架时,我可以在框架之间切换吗?
  • 伙计们,我想我做到了。所以这就是我所做的。我不知道它是否是pythonic。每当调用菜单按钮时,都会生成框架。我将其添加到列表中,然后使用 .pack_forget() 隐藏所有现有帧,即在长度为 n 的列表中,我隐藏了 n-1 个帧。这确保当前帧仍然存在,而我使用的所有其他帧都消失了。这似乎有效。感谢大家的cmets
  • 如果您不能给我们提供实际复制问题的代码,我们很难为您提供帮助。如果您希望我们花时间尝试找出您的代码,那么您也应该愿意花时间编写高质量的问题。但老实说,代码不适合我们。

标签: python tkinter


【解决方案1】:

这是我最近使用的一种方法的最小示例;关键在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()

【讨论】:

  • 嗨,这真的很有帮助。但问题是我有大约 20 个函数。这是否意味着我必须声明 20 个类。那会很艰难。我确实有点理解你在那里做了什么。当您打开新框架时,是否有更简单的方法来清除现有框架。
  • @nEO 但大概您必须在 somewhere 中定义这 20 组小部件,并且在这些 BaseFrame 子类中这样做可以将所有内容保持在一起。
【解决方案2】:

解决问题的基本方法有两种:

  1. 将所有框架堆叠在一起(例如:放在同一个网格单元中,或使用 place 和相同的选项),然后将应该可见的框架提升到顶部堆栈(使用frame.lift())。该技术的一个示例在此答案中:Switch between two frames in tkinter

  2. 每当您显示新框架时,销毁(使用.destroy() 或隐藏(使用pack_forgetgrid_forget)旧框架。

【讨论】:

    【解决方案3】:

    我有一个简单的例子。很抱歉,因为我不知道如何通过class 执行此代码。我只是使用简单的代码。但它的作品! :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()
    

    【讨论】:

      猜你喜欢
      • 2018-07-17
      • 2020-10-10
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-07
      相关资源
      最近更新 更多