2014-02-06 155 views
-2

请帮忙修复脚本。如何从另一个对象调用一个对象?

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文件后应该输出到屏幕文件的内容。而是我得到一个错误信息:

File "C:\Python33\projects\TEXTPADS\textPad_OOP\q.py", line 32, in openFile self.readFile(pointerFileOpened) File "C:\Python33\projects\TEXTPADS\textPad_OOP\q.py", line 42, in readFile self.new.insert(tkinter.END, line) AttributeError: 'WorkArea' object has no attribute 'insert'

+0

你的'WorkArea'类是一个'Frame'。你的意思是让它成为'文字'吗?或者你的意思是'workArea.insert'?你的班级结构很奇怪...... –

回答

2

的问题是,“工作区”的对象是Tkinter的Frame类的一个实例,这个类没有定义一个名为“插入”方法或属性。

WorkArea类的定义中,您定义了一个名为workArea的本地变量,该变量包含对文本窗口小部件的引用。看起来你想要插入数据到这个文本小部件。为此,需要a)将workArea(局部变量)作为实例变量,然后调用该对象的insert方法,或在WorkArea类中创建insert方法。

例如,直接调用workArea属性:

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

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

要在WorkArea类创建insert方法:

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类。也就是说,假设您没有违反合同并从WorkArea中删除insert函数。

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

+0

感谢您的详细解答! – Sergey

相关问题