Search code examples
pythontkintertkinter-text

Tkinter custom textbox class can't use def


I likely am overlooking something obvious, but this issue has ran me in circles. I want to pop up multiple text boxes and populate each on the fly. When I run the following code I get an "AttributeError", for some reason it wants me to provide something for "self" within the def.

Where is my fundamental mistake? The following is the Class contained in a separate file.

class NoninteractiveTextBox:
def __init__(self, master, location, sizew, sizeh):
    self.text_box = Text(master, width=sizew, height=sizeh, font=("Helvetica", 16))
    self.text_box.tag_configure("center", justify="center")
    self.text_box.place(x=location[0], y=location[1])
    self.text_box.tag_add("center", "1.0", "end")
    self.text_box.config(state="disabled")

def inject_text(self, event_text):
    self.text_box.config(state="normal")
    self.text_box.insert(1.0, event_text)
    self.text_box.tag_add("center", "1.0", "end")
    self.text_box.config(state="disabled")

The following is basically main.

from tkinter import *
from WidgetsTools import NoninteractiveTextBox

root = Tk()
root.title('test text')
root.geometry("1600x900")

location = [100, 500]
ntb = NoninteractiveTextBox
ntb(root, location, 80, 10)
ntb.inject_text(???, "testing text for NTB")


root.mainloop()

ntb.inject_text(???, "testing text for NTB") is the problem, I imagine this is a rookie mistake in the way I made the class itself. Any tips would help a ton.


Solution

  • ntb = NoninteractiveTextBox
    ntb(root, location, 80, 10)
    

    That's a very, shall we say, ... unusual way to try and create an instance of a class :-)

    The first line sets ntb to a reference to the class, not an instance of the class.

    Since ntb and NoninteractiveTextBox are now effectively identical references to the class, the second line is the same as if the latter were used in place of the former (which is, by the way, why it didn't fail for lack of self):

    NoninteractiveTextBox(root, location, 80, 10)
    

    In other words, it creates an instance, but immediately throws it away because you don't assign it to anything.

    And therein lies the issue with this line:

    ntb.inject_text("testing text for NTB")
    

    Because ntb is the class rather than an instance, that is considered a class method call, one which doesn't automagically provide self as the first parameter. That's why it's complaining about the missing parameter.

    You should use this instead, setting ntb to an instance of your class, and allowing it to be used as such:

    ntb = NoninteractiveTextBox(root, location, 80, 10)