Vivek Vaish
Vivek Vaish

Reputation: 11

.delete is not working inside class in tkinter

I am trying to make a tkinter desktop application (Notepad) using classes but I found an Attribute Error in my code. I made three files "menu_option.py", "textarea.py" and "window_frame.py". Run the "menu_option.py" file so that you found the error. I am using python (3.9). Also is there any another way to connect "new_file" function to menu item. Here is my code below:

menu_option.py

from tkinter import *
from textarea import TextArea
from window_frame import Window


class Menu_Option(TextArea):
    file = None

    def __init__(self, master, newfile=None):
        super().__init__(root)
        self.Menubar = 'MenuBar'
        self.Filemenu = 'FileMenu'
        self.root = self.root
        self.master = self.master
        self.newfile = newfile

    def launch(self):
        self.Menubar = Menu(self.root)
        
        self.Filemenu = Menu(master=self.Menubar, tearoff=0)
        self.Filemenu.add_command(label='New File...', command=self.newfile)
        self.Menubar.add_cascade(label='File', menu=self.Filemenu)
        
        self.root.config(menu=self.Menubar)


class Features(Menu_Option):
    def __init__(self, master):
        super().__init__(master, newfile=self.new_file)

    def new_file(self):
        global file
        self.root.title(self.title)
        file = None
        self.textarea.delete(1.0, END)


if __name__ == '__main__':
    root = Tk()
    Window(root).launch()
    TextArea(root).launch()
    Menu_Option(root).launch()
    Features(root).launch()
    root.mainloop()

textarea.py

from tkinter import *
from window_frame import Window
from tkinter.scrolledtext import ScrolledText


class TextArea(Window):
    def __init__(self, name):
        super().__init__(name)
        self.name = self.root
        self.master = 'root'
        self.textarea = 'text_area'
        self.font = 'courier 14 normal'

    def launch(self):
        self.textarea = ScrolledText(self.root, font=self.font)
        self.textarea.pack(expand=True, fill=BOTH)


if __name__ == '__main__':
    root = Tk()
    Window(root).launch()
    TextArea(root).launch()
    root.mainloop()

window_frame.py

from tkinter import *

class Window:

    def __init__(self, root):
        self.root = root
        self.geometry = '1000x550+100+100'
        self.title = 'Untitled - ProBook'

    def launch(self):
        self.root.geometry(self.geometry)
        self.root.title(self.title)


if __name__ == '__main__':
    root = Tk()
    Window(root).launch()
    root.mainloop()

Error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "D:\Installed Programs\Python\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "C:\Users\vaish\OneDrive\ProBook\menu_option.py", line 35, in new_file
    self.textarea.delete(1.0, END)
AttributeError: 'str' object has no attribute 'delete'

Upvotes: 1

Views: 108

Answers (2)

pyNeophyte
pyNeophyte

Reputation: 123

You have initialized self.textarea="text_area" in textarea.py . But when you import it in menu_option.py, you are overwriting the function launch, which is supposed to set the value of self.textarea to a ScrolledText and pack it. To solve this you have to include the code in launch function of textarea.py in the function launch of Menu_Option class.

from tkinter import *
from tkinter.scrolledtext import ScrolledText
from textarea import TextArea
from window_frame import Window


class Menu_Option(TextArea):
    file = None

    def __init__(self, master, newfile=None):
        super().__init__(root)
        self.Menubar = 'MenuBar'
        self.Filemenu = 'FileMenu'
        self.root = self.root
        self.master = self.master
        self.newfile = newfile

    def launch(self):
        self.Menubar = Menu(self.root)

        #You have to include these 2 lines of code which were overwritten
        self.textarea = ScrolledText(self.root, font=self.font)
        self.textarea.pack(expand=True, fill=BOTH)

        self.Filemenu = Menu(master=self.Menubar, tearoff=0)
        self.Filemenu.add_command(label='New File...', command=self.newfile)
        self.Menubar.add_cascade(label='File', menu=self.Filemenu)
    
        self.root.config(menu=self.Menubar)

Upvotes: 1

acw1668
acw1668

Reputation: 47193

Since Menu_Option() has override launch() function, therefore TextArea.launch() will not be executed and so instance variable textarea is still a string.

If child class wants to inherit parent class launch() functionality, you need to call the parent class launch() in its launch() function:

textarea.py

class TextArea(Window):
    ...

    def launch(self):
        super().launch()  # call parent class launch()
        self.textarea = ScrolledText(self.root, font=self.font)
        self.textarea.pack(expand=True, fill=BOTH)

menu_option.py

class Menu_Option(TextArea):
    ...

    def launch(self):
        super().launch()  # execute parent class launch()
        ...

...

if __name__ == "__main__":
    root = Tk()
    #Window(root).launch()       # <- no need to execute
    #TextArea(root).launch()     # <- no need to execute
    #Menu_Option(root).launch()  # <- no need to execute
    Features(root).launch()
    root.mainloop()

Note that Window(root).launch(), TextArea(root).launch() and Menu_Option(root).launch() are not required.

Upvotes: 1

Related Questions