gpt4 book ai didi

python - 如何从类中获取变量数据?

转载 作者:行者123 更新时间:2023-12-02 05:44:51 25 4
gpt4 key购买 nike

这是一个较长应用程序的缩短示例,其中我有多个小部件页面,收集用户输入的信息。 MyApp 将每个页面实例化为一个类。在示例中,PageTwo 希望打印 StringVar 的值,该值存储 PageOne 中 Entry 小部件的数据。

我该怎么做?我尝试过的每一次尝试都以这样或那样的异常(exception)告终。

from tkinter import *
from tkinter import ttk

class MyApp(Tk):

def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand = True)
self.frames = {}
for F in (PageOne, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky = NSEW)
self.show_frame(PageOne)

def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()


class PageOne(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
ttk.Label(self, text='PageOne').grid(padx=(20,20), pady=(20,20))
self.make_widget(controller)

def make_widget(self, controller):
self.some_input = StringVar
self.some_entry = ttk.Entry(self, textvariable=self.some_input, width=8)
self.some_entry.grid()
button1 = ttk.Button(self, text='Next Page',
command=lambda: controller.show_frame(PageTwo))
button1.grid()

class PageTwo(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
ttk.Label(self, text='PageTwo').grid(padx=(20,20), pady=(20,20))
button1 = ttk.Button(self, text='Previous Page',
command=lambda: controller.show_frame(PageOne))
button1.grid()
button2 = ttk.Button(self, text='press to print', command=self.print_it)
button2.grid()

def print_it(self):
print ('The value stored in StartPage some_entry = ')#What do I put here
#to print the value of some_input from PageOne

app = MyApp()
app.title('Multi-Page Test App')
app.mainloop()

最佳答案

利用你的 Controller

鉴于您已经有了 Controller 的概念(即使您没有使用它),您可以使用它在页面之间进行通信。第一步是在每个页面中保存对 Controller 的引用:

class PageOne(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
...

class PageTwo(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
...

接下来,向 Controller 添加一个方法,当给定类名或其他一些标识属性时,该方法将返回一个页面。在您的情况下,由于您的页面没有任何内部名称,因此您可以只使用类名称:

class MyApp(Tk):
...
def get_page(self, classname):
'''Returns an instance of a page given it's class name as a string'''
for page in self.frames.values():
if str(page.__class__.__name__) == classname:
return page
return None

note: the above implementation is based on the code in the question. The code in the question has it's origin in another answer here on stackoverflow. This code differs from the original code slightly in how it manages the pages in the controller. This uses the class reference as a key, the original answer uses the class name.

有了这个,任何页面都可以通过调用该函数来获取对任何其他页面的引用。然后,通过对该页面的引用,您可以访问该页面的公共(public)成员:

class PageTwo(ttk.Frame):
...
def print_it(self):
page_one = self.controller.get_page("PageOne")
value = page_one.some_entry.get()
print ('The value stored in StartPage some_entry = %s' % value)

在 Controller 中存储数据

从一个页面直接访问另一个页面并不是唯一的解决方案。缺点是您的页面紧密耦合。如果不对一个或多个其他类进行相应的更改,则很难在一个页面中进行更改。

如果您的页面都设计为协同工作来定义一组数据,那么将该数据存储在 Controller 中可能是明智的,这样任何给定页面都不需要知道其他页面的内部设计。这些页面可以自由地实现它们想要的小部件,而不必担心哪些其他页面可能会访问这些小部件。

例如,您可以在 Controller 中拥有一个字典(或数据库),并且每个页面负责使用其数据子集更新该字典。然后,您可以随时向 Controller 询问数据。实际上,该页面正在签署一份契约(Contract), promise 使其全局数据的子集与 GUI 中的内容保持同步。只要你维护契约,你就可以在页面的实现中为所欲为。

为此, Controller 将在创建页面之前创建数据结构。由于我们使用 tkinter,该数据结构可以由 StringVar 或任何其他 *Var 类的实例组成。不一定是这样,但在这个简单的示例中它既方便又简单:

class MyApp(Tk):
def __init__(self):
...
self.app_data = {"name": StringVar(),
"address": StringVar(),
...
}

接下来,您修改每个页面以在创建小部件时引用 Controller :

class PageOne(ttk.Frame):
def __init__(self, parent, controller):
self.controller=controller
...
self.some_entry = ttk.Entry(self,
textvariable=self.controller.app_data["name"], ...)

最后,您可以从 Controller 而不是页面访问数据。您可以丢弃 get_page,并打印如下值:

    def print_it(self):
value = self.controller.app_data["address"].get()
...

关于python - 如何从类中获取变量数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32212408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com