繁体   English   中英

Python-Tkinter-在继承自Toplevel()的类中创建的窗口小部件显示在该类之外的其他框架中,Toplevel()类为空

[英]Python - Tkinter - Widgets created inside a class inherited from Toplevel() appear in a different frame OUTSIDE the class, Toplevel() class is empty

我试图创建一个类并从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() ,但是将创建的窗口缩小到最小,并且所有GUI元素应该包含在HostGameWindow()类中的内容,而不是出现在主Application()框架中。 而且让我真正感到困扰的是,它没有给出任何错误,它只是将所有小部件放置在主应用程序框架内,而不是创建的Toplevel()

我到底在做什么错? 为什么没有在Toplevel()内放置任何小部件? 我已经花了几个小时了,没有任何意义。 如果您对我有所帮助,请告诉我。

哇,我从来没有等这么久才在这里回复,这肯定是一个很漂亮的问题,我仍然不知道该怎么办。 任何想法都将不胜感激!

我猜没人知道该怎么做...不过我会继续检查这里!

解决了! 如果创建对窗口小部件的引用,那么在同一行上创建并打包窗口小部件并不是一个好主意。 仅在仅调用Widget(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 ,因此hostgameframeNone 当您以后创建另一个窗口小部件并将其设置为主窗口时,该窗口小部件最终将进入主窗口。

因此,要解决您的问题,您需要将窗口小部件的创建与布局分开。 我个人认为这是您应始终坚持的最佳做法。 对于不需要保留对窗口小部件的引用的情况,将它们组合为一个语句是无害的。 即使这样,如果您习惯于始终将小部件的创建与小部件的布局分开,那么我认为您的代码将更易于管理。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM