如何从另一个对象调用一个?

时间:2014-02-06 14:19:00

标签: python python-3.x tkinter

请帮助修复脚本。

import tkinter
import tkinter.messagebox


class Operations():
    def new(self, parent):
        global workArea

        if workArea == True:
            tkinter.messagebox.showwarning('Warning', 'New document is already open')
        else:    
            self.new = WorkArea(parent)
            workArea = True      

    def openFile(self):
        global workArea

        if workArea == True:
            tkinter.messagebox.showwarning('Warning', 'Close the open document')
        else:
            try:
                nameOpenFile = tkinter.filedialog.askopenfilename(title = 'Open textPad file', filetypes=[("textPad files", "*.tpd")])
            except Exception:
                pass
            else:
                try:
                    pointerFileOpened = open(nameOpenFile, 'rt')
                except Exception:
                    tkinter.messagebox.showerror('Error', 'Open file error')
                else:
                    self.new(root)
                    self.readFile(pointerFileOpened)
                finally:                        
                    pointerFileOpened.close()

    def readFile(self, pointerFileOpened):
        while True:
            line = pointerFileOpened.readline()
            if len(line) == 0:
                break
            else:
                self.new.insert(tkinter.END, line)  #this is problem line
        return


class WorkArea(tkinter.Frame):
    def __init__(self, parent):
        tkinter.Frame.__init__(self, parent)
        self.parent = parent  
        self.makeWorkArea()

    def makeWorkArea(self):
        self.parent.title("My default workarea")

        workArea = tkinter.Text(self.parent)
        workArea.pack(expand = 'yes', fill = 'both')


class ToolBar(Operations, tkinter.Frame):
    def __init__(self, parent):
        tkinter.Frame.__init__(self, parent)
        self.parent = parent  
        self.makeToolBar()

    def makeToolBar(self):
        frame = tkinter.Frame(self.parent)
        frame.pack(side = 'top', fill = 'x')

        tool1 = tkinter.Button(frame, text = 'New', command = lambda: self.new(root))
        tool1.pack(side = 'left')

        tool2 = tkinter.Button(frame, text = 'Open', command = lambda: self.openFile())
        tool2.pack(side = 'left')


workArea = False

root = tkinter.Tk()
root.geometry('900x500+200+100')
toolBar = ToolBar(root)
root.mainloop()
用户打开tpd文件后,应该将该文件的内容输出到屏幕上。但我得到一条错误信息:

  

文件“C:\ Python33 \ projects \ TEXTPADS \ textPad_OOP \ q.py”,第32行,in   打开文件       self.readFile(pointerFileOpened)readFile中的文件“C:\ Python33 \ projects \ TEXTPADS \ textPad_OOP \ q.py”,第42行       self.new.insert(tkinter.END,line)AttributeError:'WorkArea'对象没有属性'insert'

1 个答案:

答案 0 :(得分:2)

问题是“WorkArea”对象是tkinter Frame类的一个实例,并且该类没有定义名为“insert”的方法或属性。

WorkArea类的定义中,您定义了一个名为workArea的局部变量,该变量包含对文本窗口小部件的引用。您似乎想要将数据插入此文本小部件中。为此,您需要a)使workArea(局部变量)成为实例变量,然后调用此对象的insert方法,或者创建insert WorkArea课程中的方法。

例如,要直接调用workArea属性:

class Operations():
    ...
    def readFile(self, pointerFileOpened):
        ...
        self.new.workArea.insert(...)
        ...

class WorkArea(...):
   ...
    def makeWorkArea(self):
        ...
        self.workArea = tkinter.Text(self.parent)
        ...

insert类中创建WorkArea方法:

class Operations():
    ...
    def readFile(self, pointerFileOpened):
        ...
        self.new.insert(...)
        ...

class WorkArea(...):
   ...
    def makeWorkArea(self):
        ...
        self._text = tkinter.Text(self.parent)
        ...

    def insert(self, *args):
        '''act as a proxy to the internal text widget'''
        self._text.insert(*args)

第二种解决方案可以说是更好的解决方案。 Operations类不应该知道WorkArea类有一个具有特定名称的内部窗口小部件。这个将两个类紧密地结合在一起:在不改变WorkArea的情况下,您无法更改Operations

通过创建自己的insert函数,您创建了一个契约,其中WorkArea承诺在某处插入文本,但调用者不需要知道在哪里。这导致松散耦合。您可以随意更改WorkArea所有内容 - 重命名窗口小部件,使用不同的窗口小部件等 - 而无需修改Operations类。也就是说,假设您没有违反合同并从insert中移除WorkArea功能。

在相关的说明中:你应该避免对这么多东西使用相同或相似的名称。有一次,您有一个名为WorkArea的类,一个名为WorkArea的变量,您设置为True或False,以及一个名为workArea的局部变量。这使您的代码很难理解。