2012-05-18 30 views
0

我想创建一个使用Tkinter的抓取用户名和密码并连接到远程服务器并执行功能的gui。我把一些乱七八糟的代码放在一起,它或多或少的工作,但是当我试图在一个整洁的模块中重新创建它时,它破裂了。它可能是一个新手Python错误,但我无法发现它。编辑:澄清,当它的工作,唯一的类是setupGui和任何方法在该类。现在我已经将gui与方法分开了,它不起作用。Python属性错误与多个类和Tkinter

class setupGui(object): 
    def __init__(self, parent): 
     ##omited general frame stuff 

     self.userIn = ttk.Entry(self.topFrame, width = 20) 
     self.userIn.grid(row = 1, column = 1) 
     self.passIn = ttk.Entry(self.topFrame, width = 20, show ="*") 
     self.passIn.grid(row = 2, column = 1) 

     #Buttons 
     self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup()) 
     self.setupbtn.grid(row = 3, column = 0, pady = 10) 

class setup(object): 
    def__init__(self): 
     self.userName = setupGui.userIn.get() 
     self.userPass = setupGui.passIn.get() 
    def startSetup(self): 
     self.another_related_fucntion # about 4 related functions actually 

if __name__ == '__main__': 
root = Tk() 
gui = setupGui(root) 
root.mainloop() 

如果我没有连接到该按钮的命令做,一切工作正常(但显然不diddly蹲除了外观漂亮)。当我连接的命令,我得到这个错误:

Traceback (most recent call last): 
File "macSetup.py", line 211, in <module> 
gui = setupGui(root) 
File "macSetup.py", line 45, in __init__ 
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup()) 
File "macSetup.py", line 69, in __init__ 
self.userName = setupGui.userIn.get() 
AttributeError: type object 'setupGui' has no attribute 'userIn' 

回答

1

在您的代码中,userIn设置为实例变量setupGui对象,而不是作为setupGui类本身的属性。

最简单的解决办法是将合并setupGuisetup类的移动startSetupsetupGui的方法,然后用command=self.startSetup在初始化setupbtn - 这个调用startSetup为绑定的方法,并因此self应参考setupGui对象,然后你可以使用例如self.userIn.get()self.passIn.get()

如果你宁愿让你在setup类纷纷走出setupGui类的逻辑,你可以这样分离出来:

class setup(object): 
    def __init__(self, username, userpass): 
     self.userName = username 
     self.userPass = userpass 

    def startSetup(self): 
     # as before 

则此方法添加到setupGui类:

def dosetup(self): 
    setup(self.userIn.get(), self.passIn.get()).startSetup() 

并实例化Buttoncommand=self.dosetup。 (我会亲自做setup类独立的功能,但我不知道有多么复杂的startSetup例行实际上是,所以我假设你有一个很好的理由,使其成为一个类。)

+0

多数民众赞成我是如何建立起来的。我通常不喜欢与guis混合使用功能。在Java中,我甚至将它们全部放在单独的包中。我尝试更改self.userName = setupGui.userIn.get()self.userName = setupGui(root).userIn.get(),但我得到了一个疯狂的递归错误。我也尝试了gui而不是根(因为它在__main__中定义),但它说它是未定义的。 哪种方法更具pythonic? – Hiroshi

+1

请参阅编辑。我认为这会对你有用。 (其实,看到最近的编辑,因为我第一次搞砸了'dosetup'。) – zigg

0

setupGui本身没有属性userIn

__init__方法setupGui中,您将属性赋予实例,而不是类。

1

command属性需要引用一个函数,但是您正在调用该函数并将结果提供给command属性。最终的结果是,您在创建按钮时调用了设置功能,而不是在单击该按钮时。事情还没有完全初始化,所以你得到的错误。

你这样做:

self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup()) 

...当你应该做这样的事情:

self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup) 

注意缺乏startSetup()的。

如果您不想实例化setup,直到单击该按钮,您有几个选择。最好的,可以说是创建一个方法:

def _launch_setup(self): 
    setup().setupGui() 
... 
self.setupbtn = ttk.Button(..., command=self._launch_setup) 

你也可以使用lambda,但在这种情况下,我推荐一个命名方法。