【问题标题】:function from module calling function , python来自模块调用函数的函数,python
【发布时间】:2017-09-12 23:52:43
【问题描述】:

好的,我需要在 more_example_funcs.py 中获取函数来更改页面。您可以在函数中看到我是如何导入的,然后尝试运行我在 example_gui.py(实际 gui)中的普通代码。这是我用来简化问题的测试脚本,以便我可以学习如何解决它们。

more_example_funcs.py

from Tkinter import *
import Tkinter as tk
import example_gui as EG

def get_text(var):
    print var.get()
    return EG.self.controller.show_frame(Page_two) ## this will not run

example_gui.py

from Tkinter import *
import Tkinter as tk
# import example_funcs as EF
import more_example_funcs as MEF


class start(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)
        self.frames = {}
        tk.Tk.title(self, "app name")
        menubar = tk.Menu(container)
        tk.Tk.config(self, menu=menubar)
        fileMenu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=fileMenu)
        fileMenu.add_command(label="Exit", command=quit)

        for F in (Page_one, Page_two, Page_three):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")


        self.show_frame(Page_one)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

class Page_one(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_one()
        self.buttons_one()
        self.entries_one()

    def labels_one(self):
        label1 = Label(self, text="Welcome to page one")
        label1.grid()

    def buttons_one(self):
        button_one = Button(self, text="go to page two", command=lambda:self.controller.show_frame(Page_two))
#        window_one_button = Button(self, text="open popup window", command=lambda:EF.popupmsg("New window 1"))
        text_one_button = Button(self, text="print entered text", command=lambda:MEF.get_text(self.entry_one_var))
        button_one.grid()
#        window_one_button.grid()
        text_one_button.grid()

    def entries_one(self):
        self.entry_one_var=StringVar()
        entry_one = Entry(self, textvariable= self.entry_one_var)
        entry_one.grid()

class Page_two(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_two()
        self.buttons_two()

    def labels_two(self):
        label2 = Label(self, text="Welcome to page two")
        label2.grid()

    def buttons_two(self):
        button_two = Button(self, text="go to page three", command=lambda:self.controller.show_frame(Page_three))
#        window_two_button = Button(self, text="open popup window", command=lambda:EF.popupmsg("New window 2"))
        button_two.grid()
#        window_two_button.grid()

class Page_three(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_three()
        self.buttons_three()

    def labels_three(self):
        label3 = Label(self, text="Welcome to page three")
        label3.grid()

    def buttons_three(self):
        button_three = Button(self, text="go to page one", command=lambda:self.controller.show_frame(Page_one))
#        window_three_button = Button(self, text="open popup window", command=lambda:EF.popupmsg("New window 3"))
        button_three.grid()
#        window_three_button.grid()

if __name__ == "__main__":        
    app = start()
#    EF.center(app)
    app.mainloop()

我试图让该函数调用 example_gui.py 中的一个新函数,该函数调用页面进行更改,但我无法正确导入函数。希望你们能帮助完成这项工作并解释它是如何工作的,以便我可以从中学习。

【问题讨论】:

  • 忽略我注释掉的东西,这是另一个不想发布和混淆的导入文件。以上所有内容也是可运行的。当点击“打印文本”按钮时页面应该改变

标签: python python-2.7 tkinter


【解决方案1】:

问题解决了。从字面上看,这是我能解决这个问题的唯一方法......

我已将我的应用分为 3 页...

example_gui_start.py

from Tkinter import *
import Tkinter as tk
import more_example_funcs as MEF

class start(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)
        self.frames = {}
        tk.Tk.title(self, "app name")
        menubar = tk.Menu(container)
        tk.Tk.config(self, menu=menubar)
        fileMenu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=fileMenu)
        fileMenu.add_command(label="Exit", command=quit)

        for F in (MEF.EG.Page_one, MEF.EG.Page_two, MEF.EG.Page_three):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")


        self.show_frame(MEF.EG.Page_one)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

if __name__ == "__main__":
    app = start()
    MEF.EG.MEF.center(app)
    app.mainloop()

more_example_funcs.py

## more_example_funcs.py
from Tkinter import *
import Tkinter as tk
import example_gui as EG
import __main__ as M

def center(toplevel):
    toplevel.update_idletasks()
    w = toplevel.winfo_screenwidth()
    h = toplevel.winfo_screenheight()
    size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
    x = w/2 - size[0]/2
    y = h/2 - size[1]/2
    toplevel.geometry("%dx%d+%d+%d" % (size + (x, y)))

def popupmsg(msg):
    popup = tk.Toplevel()
    popup.title("Information Dialog")
    label = Label(popup, text = msg)
    label.pack(side="top", pady=10)
    button = Button(popup, text = "OK", command = popup.destroy)
    button.pack()
    popup.grab_set()
    center(popup)
    popup.mainloop()


def get_text(self):
    print self.entry_one_var.get()
    M.app.show_frame(EG.Page_two)

example_gui.py

from Tkinter import *
import Tkinter as tk
import more_example_funcs as MEF

class Page_one(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_one()
        self.buttons_one()
        self.entries_one()

    def labels_one(self):
        label1 = Label(self, text="Welcome to page one")
        label1.grid()

    def buttons_one(self):
        button_one = Button(self, text="go to page two", command=lambda:self.controller.show_frame(Page_two))
        window_one_button = Button(self, text="open popup window", command=lambda:MEF.popupmsg("New window 1"))
        text_one_button = Button(self, text="print entered text", command=lambda:MEF.get_text(self))
        button_one.grid()
        window_one_button.grid()
        text_one_button.grid()

    def entries_one(self):
        self.entry_one_var=StringVar()
        entry_one = Entry(self, textvariable= self.entry_one_var)
        entry_one.grid()

class Page_two(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_two()
        self.buttons_two()

    def labels_two(self):
        label2 = Label(self, text="Welcome to page two")
        label2.grid()

    def buttons_two(self):
        button_two = Button(self, text="go to page three", command=lambda:self.controller.show_frame(Page_three))
        window_two_button = Button(self, text="open popup window", command=lambda:MEF.popupmsg("New window 2"))
        button_two.grid()
        window_two_button.grid()

class Page_three(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        self.controller = controller
        Frame.__init__(self, parent, *args, **kwargs)
        self.labels_three()
        self.buttons_three()

    def labels_three(self):
        label3 = Label(self, text="Welcome to page three")
        label3.grid()

    def buttons_three(self):
        button_three = Button(self, text="go to page one", command=lambda:self.controller.show_frame(Page_one))
        window_three_button = Button(self, text="open popup window", command=lambda:MEF.popupmsg("New window 3"))
        button_three.grid()
        window_three_button.grid()

如果您能注意到一些不同之处。 1 是我更改了 command=lambda:MEF.get_text(self),现在我可以使用我所有的“自我”。文件中的变量(example_gui.py)和我的函数(get_text)在文件(more_example_funcs.py)中......但这不是我的问题,只是让事情变得更容易一些,在这里无关紧要。

第二件改变的事情,最重要的是,在文件(more_example_funcs.py)内部我正在做“import ma​​in as M”而不是“import example_gui_start”......它们是同一个文件,但是它不会创建循环导入。在阅读了有关此问题的数小时后,Python Circular dependencies, unable to link variable to other file。这是我的赢家。

example_gui_start.py 是我运行以使用我的 GUI 的文件。 example_gui.py 是仅包含 GUI 外观代码的文件。 more_example_funcs.py 是我用来放置与按钮/条目等相关的函数的文件。

【讨论】:

    【解决方案2】:

    您希望不惜一切代价避免循环导入。最好的解决方案是将其作为类中的一种方法。

    class Page_one(tk.Frame):
        def buttons_one(self):
            text_one_button = Button(self, text="print entered text", command=self.get_text)
            button_one.grid()
    
        def get_text(self):
            print self.entry_one_var.get()
            self.controller.show_frame(Page_two)
    

    否则,您将需要使用 lambda 调用导出函数以及变量。

    您是否有理由将此函数放在单独的文件中?

    【讨论】:

    • 这只是我用来练习导入 using 函数的一个示例...我的实际 GUI 还有 10 个函数,它们从条目等中获取输入。试图将所有 GUI 放在 1 页上,然后是所有函数在另一个,所以它更整洁......当然,这也有助于我学习。
    • 你上面的代码抛出了一个语法... AttributeError: 'module' object has no attribute 'app' .... 另外,我真的很想学习如何使用模块内的函数来做到这一点在同一个文件上。但是,我不介意在 gui 文件上创建 1 个函数来调用我在其他按钮中使用的常规代码。可以通过模块内部的函数调用。但我仍然会遇到相同的属性错误语法
    • @ricky6991 啊,对。我忘记了 tkinter 会阻止循环导入完成。
    • 是的,无论我做什么,我都会一直遇到属性错误
    • 如果您在答案中添加了一些内容,然后说“没关系,这行不通”,那么您正在创建一个非常令人困惑的答案。如果它不起作用,只需将其从答案中删除。
    猜你喜欢
    • 1970-01-01
    • 2018-04-04
    • 2021-08-31
    • 2019-12-02
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    相关资源
    最近更新 更多