2012-05-18 29 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,但在這種情況下,我推薦一個命名方法。