0

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*)同じ行にウィジェットを作成してパックすることは、ウィジェットへの参照を作成せずに単に呼び出す場合にのみ機能します。

4

1 に答える 1

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そうhostgameframeですNone。後で別のウィジェットを作成し、これをマスターとして設定すると、そのウィジェットは最終的にメインウィンドウに表示されます。

したがって、問題を解決するには、ウィジェットの作成をレイアウトから分離する必要があります。個人的には、これは常に遵守すべきベストプラクティスだと思います。ウィジェットへの参照を保持する必要がない場合、それらを1つのステートメントに結合しても無害です。それでも、ウィジェットの作成とウィジェットのレイアウトを常に分離する習慣を身に付ければ、コードの管理が容易になると思います。

hostgameframe = Frame(self, bg='#999', bd=3, relief=RIDGE, padx=5, pady=5)
hostgameframe.pack({"side": "left"})
于 2013-01-15T12:39:40.000 に答える