Python-Tkinter-Widgets在继承自Toplevel()的类中创建,在类外部的不同框架中显示,Toplevel()类为空

Python-Tkinter-Widgets在继承自Toplevel()的类中创建,在类外部的不同框架中显示,Toplevel()类为空,python,python-2.7,inheritance,tkinter,Python,Python 2.7,Inheritance,Tkinter,我正在尝试创建一个类并从Toplevel()继承,以便该类的GUI元素可以包含在单独的窗口中。通常我只是从Frame()继承,但出于我的目的,我需要所有东西都在一个窗口中。我在我的GUI模板脚本中编写代码,这样我就可以在将其粘贴到我想要使用的实际脚本中之前找到如何使其工作的方法。代码如下: from Tkinter import * import socket myplayername = '' class Application(Frame): def __init__(self,

我正在尝试创建一个类并从
Toplevel()
继承,以便该类的GUI元素可以包含在单独的窗口中。通常我只是从
Frame()
继承,但出于我的目的,我需要所有东西都在一个窗口中。我在我的GUI模板脚本中编写代码,这样我就可以在将其粘贴到我想要使用的实际脚本中之前找到如何使其工作的方法。代码如下:

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()
,但创建的窗口大小尽可能小,并且应该包含在
HostGameWindow()中的所有GUI元素
class将显示在主
Application()
框架中。对我来说真正有趣的是,它没有给出任何错误,它只是将所有小部件放在主应用程序框架中,而不是创建的
Toplevel()

我到底做错了什么?为什么没有任何小部件放在
Toplevel()
中? 我已经做了好几个小时了,没有什么是有意义的。如果你知道任何对我有帮助的事情,请告诉我

哇,我从来没有在这里等过这么久的回复,这一定是个很好的问题,我还是不知道该怎么办。任何想法都非常感谢

我想没人知道这是怎么回事。。。不过我会继续在这里查的

解决了!事实证明,如果您创建一个小部件的引用,那么在同一行上创建并打包一个小部件并不是一个好主意。只有在调用
小部件(args*).pack(args*)
而不创建对它的引用时,才能在同一行上创建和打包小部件。

当执行
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
,因此
hostgameframe
None
。当您稍后创建另一个小部件并将其设置为主部件时,该小部件将进入主窗口

因此,要解决您的问题,您需要将小部件的创建与布局分开。就我个人而言,我认为这是你应该始终坚持的最佳实践。对于不需要保留对小部件的引用的情况,将它们组合成一个语句是无害的。即便如此,我认为如果您养成了总是将小部件创建与小部件布局分离的习惯,那么您的代码将更易于管理

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

通常我会将我的小部件与创建它们分开打包,我是这样写的,因为我只需要更少的代码行,我不知道这有什么不同。我昨晚一直到凌晨1点才想弄明白,我终于发现问题出在这里,谢谢你的回复。不过,我相信将来可能还有其他人会觉得这篇文章很有用。