2014-02-06 154 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

相關問題