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

2024-06-02 15:35:57 发布

您现在位置:Python中文网/ 问答频道 /正文

请帮助修改脚本。你知道吗

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'


Tags: selftruenewtkinterdeflinerootframe
1条回答
网友
1楼 · 发布于 2024-06-02 15:35:57

问题是“WorkArea”对象是tkinterFrame类的实例,这个类没有定义名为“insert”的方法或属性。你知道吗

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。这使得你的代码很难理解。你知道吗

相关问题 更多 >