【问题标题】:How do I access a list and items from another class?如何访问另一个班级的列表和项目?
【发布时间】:2021-09-19 23:20:10
【问题描述】:

我正在尝试创建一个列表,然后使用 python 和 tkinter 从列表中添加/读取项目。

我需要创建一个空白列表,并添加一些东西,然后还能够从另一个类的函数中创建的小部件中清除条目。我一直在尝试一切,但无法弄清楚如何像我需要的那样访问小部件/列表。

我不断收到的错误是 AttributeError: 'function' object has no attribute 'data'

感谢任何帮助。

from tkinter import font as tkfont

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        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 = {}

        self.frames["StartPage"] = StartPage(parent=container, controller=self)

        self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.grid(columnspan=5, rowspan=5)

        self.start = tk.Button(self, text='Start', command=lambda: self.start_frame())
        self.start.pack(side='top')


    def start_frame(self):
        data = []
        frame = tk.Frame(self)
        frame.pack(side='top', fill='both')

        entry = tk.Text(frame)
        entry.bind('<Return>', lambda event: stored_functions.print_date(self, entry=entry.get('1.0', 'end-1c')))
        entry.pack(side='top')



class stored_functions():
    def print_date(self, entry):
        StartPage.start_frame.entry.delete('1.0', tk.END)
        all_entries = StartPage.start_frame.data
        print('The last entry was {} \n\n Here is all the entries: {}'.format(entry, all_entries))


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

【问题讨论】:

  • 您能否更具体地说明错误是什么?你说你尝试了一切:你尝试了什么,这些尝试出了什么问题? 如何您需要访问小部件/列表?更具体地说明您的问题有助于我们更好地理解,以便我们为您提供帮助。
  • @SamMatzko 我不断收到错误消息 AttributeError: 'function' object has no attribute 'data'
  • 谢谢。您可能应该将此放在您的问题中,以便其他用户在不阅读 cmets 的情况下知道错误是什么。
  • 感谢您的建议。我加进去了。

标签: python python-3.x tkinter


【解决方案1】:

为了从一个类中获取变量,你需要先初始化它。在StartPage.start_frame.entry.delete('1.0', tk.END) 行中,您尝试从StartPage 类本身访问一个变量,而不是该类的instance。您还尝试访问 start_frame 方法的变量 (start_frame.entry),而不调用该方法。

当您绑定entry.bind('&lt;Return&gt;', lambda event: stored_functions.print_date(self, entry=entry.get('1.0', 'end-1c'))) 行中的条目时,您在使用stored_functions.print_date(... 而不是stored_functions().print_date(... 时会犯类似的错误(注意括号)。

当您需要访问方法之外的变量时,最好在开头使用self. 创建变量。这使得变量可以在整个类中访问,并且可以通过外部代码使用类的实例来访问。以下是修改后的代码,添加和编辑的行做了相应的标记:

import tkinter as tk
from tkinter import font as tkfont

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        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 = {}

        self.frames["StartPage"] = StartPage(parent=container, controller=self)

        self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.grid(columnspan=5, rowspan=5)

        self.start = tk.Button(self, text='Start', command=lambda: self.start_frame())
        self.start.pack(side='top')


    def start_frame(self):
        self.data = []
        frame = tk.Frame(self)
        frame.pack(side='top', fill='both')

        self.entry = tk.Text(frame) ### EDITED LINE
        self.entry.bind('<Return>', lambda event: stored_functions().print_date(self, entry=self.entry.get('1.0', 'end-1c'))) ### EDITED LINE
        self.entry.pack(side='top') ### EDITED LINE



class stored_functions():
    def print_date(self, start_page, entry): ### EDITED LINE
        start_page.entry.delete('1.0', tk.END) ### EDITED LINE
        all_entries = start_page.data ### EDITED LINE
        print('The last entry was {} \n\n Here is all the entries: {}'.format(entry, all_entries))


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

我更改了绑定条目的行,以便在按下"&lt;Enter&gt;" 时,它将StartPage 的实例和条目的文本作为参数传递给stored_functions.print_date()

请注意,当在StartPage.start_frame() 中创建条目时,它被称为self.entry,而不仅仅是entry。另请注意stored_functions.print_date() 使用start_page.entry 代替StartPage.start_frame.entry,并使用start_page.data 代替StartPage.start_frame.data。这是因为start_page 引用的是StartPage 类的实例,而不是类本身。

【讨论】:

  • 这很有帮助。感谢您花时间向我解释这一点。所以添加自我。在类中创建的任何内容的开头都使其成为类的实例,并且可以从类外部调用?我现在明白了,非常感谢。我真的不明白你在不调用方法的情况下尝试访问变量的意思(第 1 段)。我不认为我理解什么是“方法”,因为查看这段代码,所有的“代码”在到达之前都被调用了。
  • 一个“方法”只是一个类中的一个函数,它的self 作为它的def 语句中的参数。所以类内的def something(self): 是方法,而类内的def something(): 或类外的def something(self): 不是方法。
  • 我所说的“尝试访问变量而不调用方法”的意思是:当在方法(或函数)内创建变量时,它存在,如果方法(或函数)被调用。 entry 是在 start_frame 方法中定义的,所以 entry 存在于 start_frame 被调用的情况下。但是,您尝试访问start_frame.entry 而不调用start_frame,因此entry 不存在。
  • 如上所述,所有方法(类中的函数)都有一个名为 self 的参数,它类初始化时,该方法可以使用类的变量,当它被调用。但是,当类初始化时,在调用该方法时没有任何内容传递给该方法的self 参数。因此,当您将StartPage 的实例提供给stored_functions.print_date() 时,它被放入print_date()self 参数中,而不是start_page 参数中,因为没有被放置self 参数中。
  • 继续... 因此,使用stored_functions().print_date(.. 初始化 类,以便print_date() 获得self agrument。可能有很多关于 SO、教程、维基百科页面等的在线问题可以比我更好地解释这一点(并且没有长度限制:-))。如果您还不能完全理解这一点,那也没关系;你明白。继续学习并保持好奇心!
猜你喜欢
  • 2017-06-20
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 2021-02-13
相关资源
最近更新 更多