0

I am learning python tkiner from a reference book. The examples are coded in plain style, i.e., not in class format. I want to learn coding in classes because I think it helps manage long codes.

I am trying to make the text widget (named textPad) accessible to a helper function inside a class called TextEditor. The job of the helper function is to select all the text which I type. However, as soon as I run the script, I get global error that the textPad is not defined. Even when I add self. to textPad, i.e., self.textPad, I get an attribute error that Class object has no attribute textPad. The code is part of an excercise to make a full functional text editor. Below, I provide the core code which generates the error. What is the wrong with this code?

Could you please clarify my doubts: where is the best place to define helper functions: inside class or outside class? In both cases, how to make them accessable?

from tkinter import *

class TextEditor():
    def __init__(self, root):

        self.select_all() #helper function declare

        myMenu = Menu(root, tearoff=0) #Menu bar
        editMenu = Menu(root, tearoff)
        editMenu.add_command(label="Select All", accelerator="Ctrl+A", command=select_all)
        myMenu.add_cascade(label="Edit", menu=editMenu)
        root.config(menu=myMenu)

        textPad = Text(root, wrap="word", undo=True)
        textPad.pack(expand="yes", fill="both")
    def select_all(self):
        textPad.tag_add('sel', '1.0', 'end')

if __name__ == '__main__':
    root=Tk()
    app = TextEditor(root)
    root.mainloop()

This is the error:

Traceback (most recent call last):
File "C:\Python33\gui\tkguibook\textpad.py", line 21, in <module>
app = TextEditor(root)
File "C:\Python33\gui\tkguibook\textpad.py", line 6, in __init__
self.select_all() #helper function declare
File "C:\Python33\gui\tkguibook\textpad.py", line 17, in select_all
textPad.tag_add('sel', '1.0', 'end')
NameError: global name 'textPad' is not defined

Thank you in advance for your kind help!

Mohammed
  • 1,364
  • 5
  • 16
  • 32

1 Answers1

3

First of all, I advise you to watch some tutorials on object-oriented paradigm in Python without using tkinter directly.

The problem with your code is that textPad is not a property of the class, but it's a simple local variable to the __init__ method or constructor. To make it a property, you should use self to declare and then refer to the just declared property.

For example, suppose I have the following class:

class TextEditor:
    def __init__(self):
        # stuff

and you want to add a property, visible in all the points in your class, you can do it in this way:

class TextEditor:
    def __init__(self):
        self.textPad = tkinter.Text()  # using 'self' to declare a property

now, if you want to refer to that property in another method, you should use always the self:

class TextEditor:
    def __init__(self):
        self.textPad = tkinter.Text()

    def set_text(self, new_text):
        self.textPad.insert(tkinter.END, "hello")  # using 'self' to refer to the property

To know more about self.

Community
  • 1
  • 1
nbro
  • 15,395
  • 32
  • 113
  • 196
  • thank you so much for your reply. I agree with you that I must watch tutorials on OOP first. Unfortunately, I tried modefying the code as you suggested but it did not work. Thanks again. – Mohammed Jan 12 '15 at 23:44
  • @Mohammed I could try to fix your code, but it would require me some time that I don't much. Follow my advice, try first to watch how OOP works for Python, learn step by step, it's more productive, see other examples, and you will manage OOP soon :) – nbro Jan 12 '15 at 23:46
  • OK I will do that. I agree with you that nothing is more productive than self learning. – Mohammed Jan 12 '15 at 23:48
  • 1
    This is part of the problem, the other part is that you call `self.select_all()` before you define `self.textPad = Text(...)`. So when the line `self.textPad.tag_add('sel', '1.0', 'end')` is run, `self.textPad` doesn't exist yet. – fhdrsdg Jan 13 '15 at 00:29