Ozzius
Ozzius

Reputation: 139

When I'm trying to open file into tkinter text widget, but receiving error "'str' object has no attribute 'tk'"

While building an editor based on TKINTER, I have added several options into menu bar, but open command returns some error. 'str' object has no attribute 'tk'

Please be informed, I was checking with code structure & tkinter text insert document. But cant get any suitable way for this issue.

self.tk.call((self._w, 'insert', index, chars) + args) I was checking, for Custom.insert(END, contents, END + '-1c').

But still cant get rid of this on going issue.

Sorry for my bad English & Thanks in advance.

root = tk.Tk()

def open():
    print('Open an existing file from the system.')
    # return 'EOF'
    file = filedialog.askopenfile(parent=root, mode='rb', title='Select a file')
    if file != None:
        contents = file.read()
        #import pdb;
        #pdb.set_trace()
        CustomText.insert(END, contents, END + '-1c')
        file.close()

#t = threading.Thread(target=open__file)

class TextLineNumbers(tk.Canvas):
    def __init__(self, *args, **kwargs):
        tk.Canvas.__init__(self, *args, **kwargs)
        self.textwidget = None

    def attach(self, text_widget):
        self.textwidget = text_widget

    def redraw(self, *args):
        '''redraw line numbers'''
        self.delete("all")

        i = self.textwidget.index("@0,0")
        while True :
            dline= self.textwidget.dlineinfo(i)
            if dline is None: break
            y = dline[1]
            linenum = str(i).split(".")[0]
            self.create_text(2,y,anchor="nw", text=linenum)
            i = self.textwidget.index("%s+1line" % i)


class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, *args):
        # let the actual widget perform the requested action
        cmd = (self._orig,) + args
        result = self.tk.call(cmd)

        # generate an event if something was added or deleted,
        # or the cursor position changed
        if (args[0] in ("insert", "replace", "delete") or
            args[0:3] == ("mark", "set", "insert") or
            args[0:2] == ("xview", "moveto") or
            args[0:2] == ("xview", "scroll") or
            args[0:2] == ("yview", "moveto") or
            args[0:2] == ("yview", "scroll")
        ):
            self.event_generate("<<Change>>", when="tail")

        # return what the actual widget returned
        return result


class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self)
        self.vsb = tk.Scrollbar(orient="vertical", command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
        self.linenumbers = TextLineNumbers(self, width=30)
        self.linenumbers.attach(self.text)

        self.vsb.pack(side="right", fill="y")
        self.linenumbers.pack(side="left", fill="y")
        self.text.pack(side="right", fill="both", expand=True)

        self.text.bind("<<Change>>", self._on_change)
        self.text.bind("<Configure>", self._on_change)



    def _on_change(self, event):
        self.linenumbers.redraw()

    menubar = Menu(root, background='#000099', foreground='white',
                   activebackground='#004c99', activeforeground='white')
    filemanu = Menu(menubar, tearoff=0, background="grey", foreground='black',
                    activebackground='#004c99', activeforeground='white')
    menubar.add_cascade(label='File', menu=filemanu)
    filemanu.add_command(label='open', command=open)

root.config(bg='#2A2C2B', menu=Example.menubar)


if __name__ == "__main__":
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:/Users//PycharmProjects/Sub_packages/open_issue.py", line 15, in open
    CustomText.insert(END, contents, END + '-1c')
  File "C:\Users\\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3272, in insert
    self.tk.call((self._w, 'insert', index, chars) + args)
AttributeError: 'str' object has no attribute 'tk'```

Upvotes: 0

Views: 166

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 386155

Consider this code:

CustomText.insert(END, contents, END + '-1c')

You are calling the insert method on the class rather than an instance of a class.

You need to save a reference to the instance, and provide a way for your function to access that instance. In your case, the instance is saved as an attribute on the Example class, so you can save a reference to the instance of Example and use that:

def open():
    ...
    example.text.insert(END, contents, END + '-1c')
    ...


if __name__ == "__main__":
    example = Example(root)
    example.pack(side="top", fill="both", expand=True)
    root.mainloop()

Even better would be to move open into the Example class so that you can use self.text. You also should move the code for creating the menu into the __init__ function.

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        ...
        menubar = Menu(root, background='#000099', foreground='white',
                       activebackground='#004c99', activeforeground='white')
        filemanu = Menu(menubar, tearoff=0, background="grey", foreground='black',
                        activebackground='#004c99', activeforeground='white')
        menubar.add_cascade(label='File', menu=filemanu)
        filemanu.add_command(label='open', command=self.open)
        ...

    def open(self):
        ...
        self.text.insert(END, contents, END + '-1c')
        ...

Upvotes: 1

Related Questions