Tkinter ScrolledText插入文本继承E

2024-10-01 13:38:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经看过大多数可用的Tkinter ScrolledText StackOverflow帖子,其中包括对找到的继承的描述:Inheritance Tutorial和{a2}。然而,在这个具体的例子中,我似乎无法理解为什么会出现以下错误:

    textBoxClass(self.parent).textDropIn(self.parent).insert(tk.INSERT,"This is the text to add.")
AttributeError: 'NoneType' object has no attribute 'insert'

我知道我没有'insert'的属性,但是我不明白为什么基于我的类定义调用textDropIn函数没有来自{}的属性,但是我怀疑这是不正确的实例化(?)这就是函数中不能继承ScrolledText属性的原因。在

我的另一部分怀疑我必须从someGui类中的ScrolledText继承属性,以便在类方法中调用它们,但我不确定。在

完整代码:

^{pr2}$

这个问题已经被标记为一个重复的tkinter python文章,在一个get()属性调用的上下文中返回了None,但是我做了推荐给该用户的相同的行分隔编辑,但没有修复问题。如果有人能详细解释一下为什么它是重复的,我很乐意把这个问题去掉。但是,我不明白为什么会这样。在

根据Bryan的第一个答案进行编辑 这是我的理解。我做了一些编辑,但一路上遇到了几个错误。我删除了tkst.ScrolledText,因为我不正确地继承了属性并调用了它的实例。我删除了parent作为textDropIn函数中的一个属性,以及它在textBoxClass定义中的__init__中的调用。我还将self.textBox=textBoxClass(self.parent)添加到someGui类的__init__,但根据我的编辑,我遇到了TypeError和{}。目前,它是一个RecursionError,其代码为当前版本。这是由于self.textBox.textDropIn()没有传递任何参数。在

from tkinter import ttk
import tkinter as tk
import tkinter.scrolledtext as tkst


class someGui(tk.Tk):
    def __init__(self,parent):
        self.parent=parent
        self.Window()
        self.textBox=textBoxClass(self.parent) #saving the instance 

    def Window(self): 
        self.parent.configure(bg='white')
        self.parent.geometry("1000x500")
        self.parent.title("Example Window")
        self.someFrame = ttk.Frame(self.parent)
        self.someFrame.grid(row=0, column=0, sticky='nesw') #changed sticky definition for tk requirements

        textBoxSeparate=textBoxClass(self.parent) # the initial inclusion of the textbox in the frame
        self.someFunction() #no input needed

    def someFunction(self):
        #otherstuff
        self.textBox.textDropIn() #there is no parent attribute in textDropIn, so I removed it
        self.textBox.insert(tk.INSERT, "Some test text.") #split call to two lines and changed to tk.INSERT

class textBoxClass(): #removed tkst.ScrolledText in class call because instance was created in textDropIn
    def __init__(self,parent):
        self.root=parent
        super().__init__() #kept receiving TypeError: object.__init__() takes no arguments, thus removed args
        self.textDropIn() #removed parent attribute from function call

    def textDropIn(self): #removed parent attribute from definition
        self.someText = tkst.ScrolledText(master=self.root, wrap=tk.WORD, width=50, height=20)
        self.someText.grid(row=0, column=4, rowspan=7, columnspan=4, pady=20, padx=20)


def main(): 
    root =tk.Tk()
    sg=someGui(root)
    root.mainloop()

if __name__=='__main__':
    main()

Tags: thenoself属性initdefroottk
3条回答

错误告诉您,您正试图对None的对象调用insert。那么,让我们看看您在哪里调用insert

textBoxClass(self.parent).textDropIn(self.parent).insert(tk.INSERT,"This is the text to add.")

根据错误消息,我们必须得出结论:textBoxClass(self.parent).textDropIn(self.parent)是{}。果然,当我们查看textDropIn方法的定义时,它并没有显式返回任何内容。因为它不显式返回任何内容,它将返回None。因此,代码与执行None.insert(...)相同,因此会出现错误。在

有两个明显的解决方案。如果您希望能够像这样将方法链接在一起(例如:.textDropIn(...).insert(...)),则需要确保链中的每个步骤都返回原始对象。你可以这样做:

^{pr2}$

另一种方法是将一个冗长的语句分解为两个:

textBoxClass(self.parent).textDropIn(self.parent)
textboxClass(self.parent).insert(tk.INSERT,"This is the text to add.")

但是这不是调用textDropIn和{}的正确方法。相反,您需要直接在类的实例上调用它。不幸的是,您没有保存对实例的引用,因此第一件事是通过保存实例来解决此问题:

class someGui(tk.Tk):
    def __init__(self,parent):
        self.parent=parent
        self.Window()
        self.textBox = textBoxClass(self.parent)

然后,可以调用该实例上的方法:

def someFunction(self):
    #otherstuff
    self.textBox.textDropIn(self.parent)
    self.textbox.insert(tk.INSERT,"This is the text to add.")

由于您从未在textDropIn中使用parent属性,因此我建议从定义和调用中删除该参数。在

如果你的名字都是大写字母,那么你就更容易理解了。您应该将textBoxClass更改为TextBoxClass,并将{}更改为{}。这种命名约定在python世界中是通用的。有关标准命名约定的详细信息,请参见PEP8。在

还有一个问题。textBoxClass既继承了ScrolledText,又创建了它的一个实例。你应该做一个或另一个。我不太清楚您要完成什么,但是扩展现有类的常规方法是这样的(注意super的用户):

class textBoxClass(tkst.ScrolledText):
    def __init__(self,parent):
        self.root=parent
        super().__init__(self, parent)
        self.textDropIn(self.root)

代码中的另一个问题是导入tkinter两次:

from tkinter import *
...
import tkinter as tk

这使得你的代码很难理解。你需要选择一种导入方法并坚持下去。我个人认为第二个版本是最好的,因为它遵循PEP8和python的zen(显式比隐式好)。在

最后还有一个问题。您正在创建两个根窗口,而tkinter程序只能有一个(除非在非常特殊的情况下,这不是)。一个是在您执行root = tk.Tk()时创建的,第二个是在您执行sg=someGui(root)时创建的,因为someGui继承了tk.Tk。为了使问题复杂化,您没有正确地调用超类__init__方法,因此someGui实例的构造不正确。这就是您在更新中提到的递归错误的根源。在

几周前,通过一位朋友的贡献和我自己的实验,我找到了一个解决问题的方法。在

我知道由于解决方案所需的Tkinter AttributeError,这已经被否决了,但是AttributeError修复的简单集成并没有解决我的问题,这是一个与我最初的问题相关的未知错误。这里是回答我最初问题的最佳答案。在

我要理解的最大问题是textBoxClasstextDropIn函数中的super().__init__调用。在此之前,我是从tkst.ScrolledText继承的,但我创建的小部件不正确。在

最后的解决方案允许我调用textBoxClass的类实例,并将文本写入与someGui类相关联的所有子函数的窗口中,这是我最初的目标。在

我在这里留下了注释代码,以反映一些过去没有功能的想法。在

from tkinter import ttk
import tkinter as tk
import tkinter.scrolledtext as tkst


class someGui(tk.Tk):
    def __init__(self, parent):
        self.parent=parent
        self.textBox=textBoxClass(self.parent) #saving the instance
        self.Window()

    def Window(self): 
        print("window")
        self.parent.configure(bg='white')
        self.parent.geometry("1000x500")
        self.parent.title("Example Window")
        self.someFrame = ttk.Frame(self.parent)
        self.someFrame.grid(row=0, column=0, sticky='nesw') #changed sticky definition for tk requirements

        # textBoxSeparate=textBoxClass(self.parent) # the initial inclusion of the textbox in the frame
        # textBoxSeparate.place(relx=0.5, rely=0.025, anchor='nw') #added this so textBoxSeparate doesn't overlap textbox
        # textBoxSeparate.insert(tk.INSERT, "textBoxSeparate sample text")
        self.someFunction() #no input needed
        # self.newFunction()

    def someFunction(self):
        #Both of the following ways of adding text work
        self.textBox.textDropIn() #there is no parent attribute in textDropIn, so I removed it
        self.textBox.insert(tk.INSERT, "textbox sample text\n") #split call to two lines and changed to tk.INSERT
        self.newFunction()

    def newFunction(self):
        self.textBox.insert(tk.INSERT,"another line of text")

class textBoxClass(tkst.ScrolledText): 
    def __init__(self, parent):
        self.root = parent
        #super().__init__(...) allows this class to inherit the tkst.ScrolledText class. Therefore, initializing the textBoxClass 
        #will automaticaly allow it to have all the same methods/attributes as initializing tkst.ScrolledText(), in addition to the methods/attr you add below.
        super().__init__(master=self.root, wrap=tk.WORD, borderwidth=1, relief="solid",width=50, height=20) #added a border for better visualization
        #self.textDropIn() #removed parent attribute from function call

    def textDropIn(self): #removed parent attribute from definition
        self.grid(row=0, column=4, rowspan=7, columnspan=4, pady=20, padx=20)
        # self.insert(tk.INSERT, "textDropIn sample text\n")

def main(): 
    root =tk.Tk()
    sg=someGui(root)
    root.mainloop()

if __name__=='__main__':
    main()
from tkinter import ttk
import tkinter as tk
import tkinter.scrolledtext as tkst


class SomeGui(tk.Tk):
    def __init__(self):
        super().__init__()

    self.textBox=TextBoxClass(self) #saving the instance 
    self.configure(bg='white')
    self.geometry("1000x500")
    self.title("Example Window")
    self.someFrame = ttk.Frame(self)
    self.someFrame.grid(row=0, column=0, sticky='nesw') #changed sticky definition for tk requirements

    self.someFunction() #no input needed

    def someFunction(self):
        #otherstuff
        self.textBox.textDropIn() #there is no parent attribute in textDropIn, so I removed it
        self.textBox.someText.insert(tk.INSERT, "here we go")

class TextBoxClass(tkst.ScrolledText): #removed tkst.ScrolledText in class call because instance was created in textDropIn
    def __init__(self,parent):
        self.root=parent
        tkst.ScrolledText.__init__(self) #kept receiving TypeError: object.__init__() takes no arguments, thus removed args
        self.textDropIn()

    def textDropIn(self): #removed parent attribute from definition
        self.someText = tkst.ScrolledText(master=self.root, wrap=tk.WORD, width=50, height=20)
        self.someText.grid(row=0, column=4, rowspan=7, columnspan=4, pady=20, padx=20)


def main(): 
    sg=someGui()
    sg.mainloop()

if __name__=='__main__':
    main()

好的,所以我做了一些更改,并使它与您的someFunction方法一起工作。在与Bryan在评论中交谈后,我意识到我们忘了初始化SomeGui类中的父类,这可能是导致递归错误的原因。我很可能也在那里。在

相关问题 更多 >