2013-01-14 53 views
0

我試圖創建一個類和從Toplevel()繼承使得的GUI元素該類可以包含在一個單獨的窗口中。通常我只會繼承Frame(),但爲了我的目的,我需要一切都在窗口中。我寫在我的GUI模板腳本代碼,這樣我可以計算出如何得到它的工作之前,我把它粘在實際的劇本我想用它下面是代碼:的Python - Tkinter的 - 從Toplevel的()繼承的類內部創建窗口小部件顯示在不同的幀OUTSIDE類,Toplevel窗口()類是空

from Tkinter import * 
import socket 

myplayername = '' 

class Application(Frame): 
    def __init__(self, master=None): 
     Frame.__init__(self, master) 
     self.pack() 

     class InfoLabel(Frame): 
      def __init__(self, name, value, bgc, nfgc, vfgc, master=None): 
       Frame.__init__(self, master) 
       self.pack() 
       Label(master=self, text=name, bg=bgc, fg=nfgc).pack({"side": "left"}) 
       Label(master=self, text=value, bg=bgc, fg=vfgc).pack({"side": "left"}) 

     class LabelEntry(Frame): 
      def __init__(self, name, variable, bgc, fgc, entrysize, master=None): 
       Frame.__init__(self, master) 
       self.pack() 
       Label(master=self, text=name, bg=bgc, fg=fgc).pack({"side": "left"}) 
       Entry(master=self, textvariable=variable, bg=bgc).pack({"side": "left"}) 

     class HostGameWindow(Toplevel): 
      def __init__(self): 
       global myplayername 
       Toplevel.__init__(self) 
       self.title('Host a Game') 
       hostname = socket.gethostname() 
       hostipaddr = socket.gethostbyname(hostname) 
       hostport = 11489 
       players = 0 

       portsv = StringVar(value=str(hostport)) 
       numofplayers = StringVar(value=str(players)) 
       myname = StringVar(value=myplayername) 

       hostgameframe = Frame(master=self, bg='#999', bd=3, relief=RIDGE, padx=5, pady=5).pack({"side": "left"}) 
       hoststatusframe = Frame(master=self, bg='white', bd=3, relief=RIDGE).pack({"side": "left"}) 
       hostbuttonframe = Frame(master=hostgameframe, bd=2, relief=RAISED, padx=5, pady=5).pack({"side": "bottom"}) 
       InfoLabel(master=hostgameframe, name='Hostname:', value=hostname, bgc='#999', nfgc='blue', vfgc='red').pack({"side": "top"}) 
       InfoLabel(master=hostgameframe, name='IP Address:', value=hostipaddr, bgc='#999', nfgc='blue', vfgc='red').pack({"side": "top"}) 
       LabelEntry(master=hostgameframe, name='Host on port:', variable=portsv, bgc='#999', fgc='blue', entrysize=len(str(hostport))).pack({"side": "top"}) 
       LabelEntry(master=hostgameframe, name='Players Joining:', variable=numofplayers, bgc='#999', fgc='blue', entrysize=2).pack({"side": "top"}) 
       LabelEntry(master=hostgameframe, name='Player Name:', variable=myname, bgc='#999', fgc='blue', entrysize=16).pack({"side": "top"}) 
       Button(master=hostbuttonframe, text='Host Game', width=10).pack({"side": "left"}) 
       Button(master=hostbuttonframe, text='Start Game', width=10).pack({"side": "left"}) 

      def close(): 
       self.destroy() 

     def HostGameDialog(): 
      HostGameWindow() 

     Button(master=self, text='Host a Game', command=HostGameDialog).pack() 




root = Tk() 
app = Application(master=root) 
#root.wm_iconbitmap(default='INSERT ICON HERE') 
#root.wm_title("TITLE OF PROGRAM") 
#app.master.maxsize(640, 480) 
app.master.minsize(640, 480) 
app.master.resizable(0, 0) 
app.mainloop() 
app.quit() 

現在出於某種原因,當我點擊「舉辦一場遊戲」按鈕,它會調用HostGameDialog()功能,它創造了HostGameWindow(),但被創建的窗口大小,縮小小,因爲它可以而且應該被包含在所有GUI元素HostGameWindow()類改爲出現在主要的Application()幀中。而對我來說真的很奇怪的是它沒有給出任何錯誤,它只是將所有的小部件放在主應用程序框架內,而不是創建的Toplevel()

我做錯了什麼?爲什麼不在Toplevel()內部放置任何小部件? 我已經好幾個小時了,沒有任何意義。如果你知道任何可能對我有幫助的事情,請告訴我。

哇,我從來沒有等待回答這麼久這裏之前,這一定是一個非常漂亮的問題,我還是不知道該怎麼辦。任何想法都非常感謝!

我想沒有人知道本作的什麼......我會繼續在這裏雖然檢查!

已解決!如果你創建了一個對它的引用,那麼在同一行上創建並打包一個小部件並不是一個好主意。在同一行上創建和打包小部件只有在您調用Widget(args*).pack(args*)而不創建對其的引用時纔有效。

回答

1

當你做x=a().b(),什麼是存儲在x爲b()結果。

考慮下面的代碼行:

hostgameframe = Frame(self, bg='#999', bd=3, 
    relief=RIDGE, padx=5, pady=5).pack({"side": "left"}) 

如果我們摺疊所有的選項(清晰度)我們留下這個:

hostgameframe = Frame(...).pack(...) 

你能看到發生了什麼? hostgameframe正在設置爲pack(...)的結果。 pack總是返回None,所以hostgameframeNone。當您稍後創建另一個小部件並將其設置爲主控時,該小部件將在主窗口中結束。

所以,解決你的問題,你需要將控件創建從佈局中分離出來。我個人認爲這是你應該始終堅持的最佳做法。對於不需要保留對小部件引用的情況,將它們組合成一個語句是無害的。即便如此,如果您習慣將小部件創建與小部件佈局分開,我認爲您的代碼將更易於管理。

hostgameframe = Frame(self, bg='#999', bd=3, relief=RIDGE, padx=5, pady=5) 
hostgameframe.pack({"side": "left"}) 
+0

通常我會將自己的小部件分開包裝而不是創建它們,因爲我只是想要更少的代碼行,並且我不知道它有所作爲。我昨天早上到凌晨1點試圖找出它,然後我終於發現是問題所在,但無論如何,感謝您的回覆,但我確定有可能是其他人可能會發現這篇文章有用的未來。 –

相關問題