Tkinter ScrolledText Insert Text Inheritance Error

tkinter scrolledtext clear
tkinter text
tkinter text editor
tkinter scrolledtext horizontal scrollbar
tkinter output text box
tkinter add text to frame
tkinter scrolledtext font
tkinter scrolledtext wrap

I have looked at most of the available Tkinter ScrolledText StackOverflow posts including descriptions of inheritance found : Inheritance Tutorial and Inheritance with Classes. Yet, I cannot seem to understand in this specific example, why I get the following error:

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

I understand that I do not have the attribute of 'insert' present, but I do not understand why the textDropIn function does not have the attributes from ScrolledText based on my class definition call of class textBoxClass(tkst.ScrolledText):, however I suspect it is improper instantiation (?) that is the reason why the inheritance of the ScrolledText attributes are not available in the function.

Another part of me suspects that I have to inherit attributes from ScrolledText within the someGui class in order to call them in the class methods, but I am not sure.

Full code:

from tkinter import *
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()
        textBoxInstance=textBoxClass(self.parent)

    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=(N,S,E,W))

        textBoxSeparate=textBoxClass(self.parent)
        self.someFunction()

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

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

    def textDropIn(self,parent):
        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()

This question has been marked as a duplicate as another tkinter python post with a None return in the context of a get() attribute call, but I have made the same line separation edit that was recommended to that user without fixing the problem. If someone can explain, in detail, why it is a duplicate, I would be happy to remove the question. But, I cannot understand why it is.

Edit based on first answer by Bryan This was my understanding. I made edits but ran into several errors along the way. I removed the tkst.ScrolledText because I was improperly inheriting attributes and calling and instance of it. I removed parent as an attribute in textDropIn function and its respective call in __init__ in the textBoxClass definition. I have also added the self.textBox=textBoxClass(self.parent) to the __init__ of the someGui class, but I have run into TypeError and RecursionError based on my edits. At present, it is a RecursionError with the code in the current version. Which is on account of the self.textBox.textDropIn() with no arguments passed through.

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()

The error is telling you that you're trying to call insert on an object that is None. So, let's look at where you're calling insert:

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

Based on the error message we must conclude that textBoxClass(self.parent).textDropIn(self.parent) is None. And sure enough, when we look at the definition of the textDropIn method, it doesn't explicitly return anything. Because it doesn't explicitly return anything, it will return None. Thus, the code is the same as if you had done None.insert(...), and hence the error that you get.

There are two obvious solutions. If you want to be able to chain methods together like this (eg: .textDropIn(...).insert(...)), you need to make sure every step in the chain returns the original object. You can do this like so:

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

The other method is to break that one long statement into two:

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

However, that is not the proper way to call textDropIn and insert. Instead, you need to be calling it directly on the instance of the class. Unfortunately, you aren't saving a reference to the instance, so the first thing is to fix that by saving the instance:

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

Then, you can call the methods on that instance:

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

Since you never use the parent attribute in textDropIn, I recommend removing that parameter both from the definition and from the call.

Also, your code will be easier to understand if you start all class names with an uppercase letter. You should change textBoxClass to TextBoxClass and someGui to SomeGui. This naming convention is universal in the python world. For more information on standard naming conventions, see PEP8.

There's another problem. The textBoxClass is both inheriting from ScrolledText and creating an instance of it. You should do one or the other. I can't quite tell what you're trying to accomplish, but the normal way to extend an existing class is with something like this (note the user of super):

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

Yet another problem in the code is that you are importing tkinter twice:

from tkinter import *
...
import tkinter as tk

This makes your code very hard to understand. You need to pick one method of importing and stick with it. Personally I think the second version is the best because it adheres to PEP8 as well as the zen of python (explicit is better than implicit).

Finally, there is one more problem. You are creating two root windows, and a tkinter program can only have one (except under very unusual circumstances, which this is not). One is created when you do root = tk.Tk(), and the second is when you do sg=someGui(root), since someGui inherits from tk.Tk. To compound the problem you aren't properly calling the superclass __init__ method, so the someGui instance is not properly constructed. That is the root of the recursion error you wrote about in your update.

Programming Python: Powerful Object-Oriented Programming, PP4E\Gui\Tour simpleedit.py add common edit tools to ScrolledText by inheritance; composition scrolledtext import Scrolled Text # here, not Python's class SimpleEditor(ScrolledText): self. text. insert (INSERT, text) except Tcl Error: pass # not to be pasted on Find(self): target = askstring('SimpleEditor', '​Search String? The tkinter.scrolledtext module provides the text widget along with a scroll bar. This widget helps the user enter multiple lines of text with convenience. Instead of adding a Scroll bar to a text widget, we can make use of a scrolledtext widget that helps to enter any number of lines of text. Example 1 : Python code displaying scrolledText widget.

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()

Ok so Ive made some changes and got it all working with your someFunctionmethod. I realised after talking with Bryan in the comments that we forgot to initialize the parent class in your SomeGui class which was probably the cause for the recursion error we were getting. There is probably a way to tidy up TextBoxClass that I am overlooking too.

Python Tkinter - ScrolledText Widget, scrolledtext module provides the text widget along with a scroll bar. This widget helps the user enter multiple lines of text with convenience. Instead of adding a  I'm trying to make a Tkinter entry box, but need more space than just one line. It seems that . self.scroll = ScrolledText.ScrolledText(self.tk).pack() is the best looking way to do it right now, but I dont know how to get the inputted text from self.scroll and use it for something else, theres no clear documentation on it either. Does anyone know?

By the contribution of a friend and my own experimentation integrating elements of what the commenters said, I came to a solution for my problem a couple weeks ago.

I know that this has been downvoted by virtue of the Tkinter AttributeError that was needed for the solution, but a simple integration of the AttributeError fix did not solve my problem and that was an unknown error related to my original question. Here is the best answer to answer my original question.

The biggest issue for me to comprehend was the super().__init__ call in the textDropIn function within the textBoxClass. Prior to that I was inheriting from tkst.ScrolledText but I was creating the widget improperly.

The final solution allows me to call upon the class instance of textBoxClass and write text to the window in all of the child functions associated with the someGui class, which was my original goal.

I have left the commented code in there to reflect some of the past ideas that were nonfunctional.

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()

Python: module ScrolledText, Methods inherited from Tkinter.Text: bbox(self, *args): Return a tuple of (x,y,width,​height) which gives the bounding box of the Generates an error when the redo stack is empty. as all the insert and delete commands that are recorded The following are code examples for showing how to use tkinter.scrolledtext.ScrolledText().They are from open source Python projects. You can vote up the examples you like or vote down the ones you don't like.

Section 8.4. Text, a simple text or file viewer component print 'PP2E scrolledtext' from Tkinter import add common edit tools to scrolled text by inheritance; # composition store text in file def onCut(self): text = self.text.get(SEL_FIRST, SEL_LAST) # error if no​  Tkinter is a GUI toolkit used in python to make user-friendly GUIs.Tkinter is the most commonly used and the most basic GUI framework available in python. Tkinter uses an object-oriented approach to make GUIs. Note: For more information, refer to Python GUI – tkinter. Text Widget. Text Widget is used where a user wants to insert multiline

Text, For instance, the Tkinter Text widget was powerful enough to implement the Grail web add common edit tools to scrolled text by inheritance; # composition text in file def onCut(self): text = self.text.get(SEL_FIRST, SEL_LAST) # error if no  This looks nice but doesn't work if you try to send a log message from another thread (despite the comment) because we are passing the text widget with the logging handler to the other thread. And you can only write to a tkinter widget from the main thread. This is explained in another StackOverflow question but I didn't like the proposed

Logging to a Tkinter ScrolledText Widget, __init__(self) # Store a reference to the Text it will log to self.text = text def def append(): self.text.configure(state='normal') self.text.insert(tk. ERROR level to show that different colors are associated to the log levels """ def  The tkinter.scrolledtext module provides a class of the same name which implements a basic text widget which has a vertical scroll bar configured to do the “right thing.” Using the ScrolledText class is a lot easier than setting up a text widget and scroll bar directly. The constructor is the same as that of the tkinter.Text class.

Comments
  • Your method textDropIn doesn't return anything, yet you are trying to use a method insert with its return. Likely you want the object from textBoxClass. You likely have the same issue as this post.
  • Possible duplicate of Tkinter: AttributeError: NoneType object has no attribute get
  • @busybear I do not understand. Do I have to have a return from my function textDropIn? And what do you mean by "...you want the object from textBoxClass"?
  • Might need to call the parent classes init under your classes init?
  • @GeraldLeese would that look like textBoxClass.__init__() in the someGui __init__ definition?
  • Thank you very much for your answer. I understood most all of what you said, or so I thought, however I have run into a recursion error related to the self.textDropIn() call. I have added the updated code with some comments to reflect the specific edits. One thing I forgot to mention was that I fixed the import calls as well!
  • Thanks for your answer, but my initial goal was to update the text in the ScrolledText window created within textDropIn within the someFunction attribute of someGui.
  • I think you have to create the scrolled text instance in the someGui class then
  • a class instance is created in self.textBox=textBoxClass(self.parent) within the someGui __init__ definition
  • @whisperquiet I edited the piece of code it should work the way you wanted now