【问题标题】:Tkinter pages updated from separate files从单独文件更新的 Tkinter 页面
【发布时间】:2019-12-30 20:11:29
【问题描述】:

使用最初发布的以下代码here 我如何使用带有PageList() 命令的第4 个模块和它下面的新页面类在我的WindowHandler() 类中显示它?通过其他研究,我相信您将不得不停止使用 Windowhandler() 作为主应用程序类的实例。

这样做的目的是让堆叠的帧在不同的文件中,而每个文件都可以更新frames={} 列表,而无需将其添加到主类中。 here 为不同的页面提供了类似的示例,但对这些页面的调用仍必须添加到主类中。

导航.py

import tkinter as tk
from Page import PageList
import Mypages

class Windowhandler(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand= True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        PageList("Page1", container, self, Mypages.PageOne)
        PageList("Page2", container, self, Mypages.PageTwo)
        self.show_frame("Page1")

    def show_frame(self, cont):
        frameref = PageList.frames[cont]
        print(frameref)
        frameref.tkraise()



app = Windowhandler()
app.mainloop()

页面.py

class PageList():
frames = {}
def __init__(self, name, parent, cont, ref):
    self.frames[name] = ref(parent=parent, controller=cont)

我的页面.py

    import tkinter as tk

    class PageOne(tk.Frame):
        def __init__(self, parent, controller):
            this = tk.Frame.__init__(self, parent)
            label = tk.Label(this, text="Welcome to Page 1")
            label.pack(pady=10, padx=10)

            button1 = tk.Button(this, text="Back to Home",
                        command=lambda: controller.show_frame("Page2"))
            button1.pack()

    class PageTwo(tk.Frame):
        def __init__(self, parent, controller):
            this = tk.Frame.__init__(self, parent)
            label = tk.Label(this, text="Welcome to Page 2")
            label.pack(pady=10, padx=10)

            button1 = tk.Button(this, text="Back to Home",
                        command=lambda: controller.show_frame("NewPage"))
            button1.pack()

Psuedo.py

import tkinter as tk
import Nav

PageList("NewPage", Nav.container, WindowHandler, NewPage)

class NewPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        btn1 = Nav(self, text="A Button" command=lambda: Controller.show_frame("Page1"))
        btn1.pack(pady=(10, 4))

【问题讨论】:

  • 听起来您想创建一个插件系统,只需导入文件即可插入新页面。我说的对吗?
  • 你是对的我有一个 importlib 设置,其中新文件被导入到我的主文件中,我希望每个新文件都扩展菜单,以便每个文件都有自己的菜单,是的,这可能是超过我的技能水平。

标签: python python-3.x tkinter


【解决方案1】:

下面的代码是我设法解决上述问题的代码,每个帧都存储在子文件夹中的不同文件中,尽管它是使用 importlib 加载的,因为这是我的应用程序所需要的。

这是通过在每个文件 addnav 中拥有一个通用函数来实现的,该函数将由 Main.py 文件调用,该函数使用 Resource.py 中的另一个函数来跟踪帧,并且在所有文件之间共享一个最终的Dstore() 类,它返回有关子文件的数据。


main.py

from os import listdir
from importlib import import_module
from Resource import *


# Create our main window under the Windowhandler class.
class Windowhandler(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.title(self, "Stacked frames + Stacked window with dynamic imports")
        tk.Tk.geometry(self, "800x800")
        tk.Tk.state(self, "zoomed")

    # Used for displaying stacked frames from frames list in Resource.py
    def show_frame(self, cont):
        frame = Addnav.frames[cont]
        frame.tkraise()


# Find all modules inside module subfolder, import and return list of references.
def importscript(**kwargs):
    kwargs["pdir"] = kwargs.get("pdir", "/Users/Main/PycharmProjects/Plugin-Stacked-Frames/Modules")
    pdir = kwargs["pdir"]
    mlist = {}

    for fi, file in enumerate(listdir(pdir)):
        if file.endswith(".py") and file != "__init__.py":
            module = import_module("Modules." + file.strip(".py"))
            module.Dstore()
            notify = module.Dstore.Info
            print("Imported " + notify["name"])
            mlist[fi] = module
    return mlist


# This is our root menu that has a button for each sub menu of our sub files.
class MenuHome(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="white")
        tk.Label(self, text="Root Menu").pack(pady=(20, 5))
        # Enumerate through frames and add a button object referenced to each sub files menu.
        for idx, fref in enumerate(Addnav.frames):
            sinfo = sub[idx].Dstore.Info
            btn = tk.Button(self, text=sinfo["name"], command=lambda fref=fref: controller.show_frame(fref))
            btn.pack()


sub = importscript()
app = Windowhandler()

# Create 2 containers 1 for the menu 1 for the main workspace.
container = tk.Frame(app)
container.pack(side="left", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)

for N in sub:
    pref = sub[N].Dstore.Info
    sub[N].addnav(pref["reference"], container, app)

Addnav("MenuHome", container, app, MenuHome)
Windowhandler.show_frame(container, "MenuHome")

app.mainloop()

Subfile1.py(放在名为 Modules 的子文件夹中)

from Resource import *


# For getting information about the individual subfile.
class Dstore():
    Info = {}
    def __init__(self):
        self.Info["reference"] = "Menu1"
        self.Info["name"] = "Sub Menu 1"


# Calls the shared resource Addnav function to add the menu.
def addnav(name, container, app):
    Addnav(name, container, app, Menu1)


# The menu class for this file.
class Menu1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="blue")
        tk.Label(self, text="Welcome to subfile menu 1").pack(pady=(20, 5))
        btn1 = tk.Button(self, text="Home", command=lambda: controller.show_frame("MenuHome"))
        btn1.pack()
        btn2 = tk.Button(self, text="Subfile menu 2", command=lambda: controller.show_frame("Menu2"))
        btn2.pack()

Subfile2.py(放在名为 Modules 的子文件夹中)

from Resource import *


# For getting information about the individual subfile.
class Dstore():
    Info = {}
    def __init__(self):
        self.Info["reference"] = "Menu2"
        self.Info["name"] = "Sub Menu 2"


# Calls the shared resource Addnav function to add the menu.
def addnav(name, container, app):
    Addnav(name, container, app, Menu1)


# The menu class for this file.
class Menu1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="red")
        tk.Label(self, text="Welcome to subfile 2 menu").pack(pady=(20, 5))
        btn1 = tk.Button(self, text="Home", command=lambda: controller.show_frame("MenuHome"))
        btn1.pack()
        btn2 = tk.Button(self, text="Subfile Menu 1", command=lambda: controller.show_frame("Menu1"))
        btn2.pack()

资源.py

import tkinter as tk


class Addnav:
    frames = {}

    def __init__(self, name, parent, cont, ref):
        self.frames[name] = ref(parent=parent, controller=cont)
        self.frames[name].grid(row=0, column=0, sticky="nsew")

用于使视觉明显的颜色,请注意我不是 python 大师,在这个其他功能代码中可能有十几个或更多错误,请评论编辑。

【讨论】:

    猜你喜欢
    • 2017-01-24
    • 2021-12-15
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多