Tkinterプログラムを設定する2つの基本的な方法を見てきました。どちらか一方を優先する理由はありますか?
from Tkinter import *
class Application():
def __init__(self, root, title):
self.root = root
self.root.title(title)
self.label = Label(self.root, text='Hello')
self.label.grid(row=0, column=0)
root = Tk()
app = Application(root, 'Sample App')
root.mainloop()
そして
from Tkinter import *
class Application(Frame):
def __init__(self, title, master=None):
Frame.__init__(self, master)
self.grid()
self.master.title(title)
self.label = Label(self, text='Hello')
self.label.grid(row=0, column=0)
app = Application('Sample App')
app.mainloop()
私が好むオプションは、クラスTkから継承することです。ウィンドウは実際にはアプリケーションなので、これはより合理的な選択だと思います。 Frame
から継承しても、Button
またはCanvas
またはLabel
から継承しても意味がありません。ルートは1つしか持てないため、それが継承元であることは理にかなっています。
また、import Tkinter as tk
ではなくfrom Tkinter import *
としてインポートすると、コードが読みやすくなると思います。次に、すべての呼び出しでtk
モジュールについて明示的に言及します。これをすべてのモジュールに推奨することはしませんが、Tkinterを使用することは理にかなっています。
例えば:
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.label = tk.Label(text="Hello, world")
self.label.pack(padx=10, pady=10)
app = SampleApp()
app.mainloop()
*注:最初にこの回答を書いて以来、私は自分の立場を変更しました。 Frame
ではなくTk
から継承することを好みます。どちらにしても本当の利点はありません。それは、何よりも哲学的な選択です。いずれにせよ、Frame
から継承するかTk
から継承するかに関係なく、どちらも、何も継承しないコードの最初の例よりも優れていると思います。
Frame
から継承するTk
よりもわずかな利点の1つは、アプリケーションで複数の同一のウィンドウをサポートする場合です。その場合、Frame
から継承すると、最初のウィンドウをルートの子として、追加のウィンドウをToplevel
のインスタンスの子として作成できます。ただし、これを実行する必要があるプログラムはほとんどありません。
Tkinterプログラムをどのように構造化すべきかについての詳細は、質問 Python Tkinterプログラムの構造 の my answer を参照してください。
通常、フレームは 他のウィジェットのジオメトリマスター として使用されます。通常、アプリケーションには多数のウィジェットがあるため、それらをすべてフレームに含めるか、少なくともフレームを使用してborderwidth
、パディング、またはその他の便利な機能を追加することがよくあります。
Webで見つかる多くのサンプルスニペットは、最短のコードでいくつかの機能をデモンストレーションしたいだけなので、Frameを使用しません。
したがって、必要な場合はフレームを使用し、そうでない場合は使用しないでください。
編集:GUIを編成する最良の方法はこれで提供されると思います Tkinterチュートリアル :
simpleApp.py:
import Tkinter as tk
class SimpleApp(object):
def __init__(self, master, **kwargs):
title=kwargs.pop('title')
frame=tk.Frame(master, **kwargs)
frame.pack()
self.label = tk.Label(frame, text=title)
self.label.pack(padx=10,pady=10)
if __name__=='__main__':
root = tk.Tk()
app = SimpleApp(root,title='Hello, world')
root.mainloop()
これは、SimpleApp
がobject
ではなくFrame
から継承するという点で、主にfirstの例に似ています。 Frame
メソッドをオーバーライドしないため、Frame
をサブクラス化するよりも良いと思います。私はSimpleApp
をFrame
ではなくFrame
と考えるのが好きです。
SimpleApp
サブクラスobject
を使用すると、tk.Tk
をサブクラス化するよりも大きな利点があります。ただし、SimpleApp
を大きなアプリに簡単に埋め込むことができます。
import simpleApp
import Tkinter as tk
class BigApp(object):
def __init__(self, master, **kwargs):
title=kwargs.pop('title')
frame=tk.Frame(master, **kwargs)
frame.pack()
self.simple = simpleApp.SimpleApp(frame,title=title)
frame.pack(padx=10, pady=10)
self.simple2 = simpleApp.SimpleApp(frame,title=title)
frame.pack()
if __name__=='__main__':
root = tk.Tk()
app = BigApp(root,title='Hello, world')
root.mainloop()
したがって、simpleApp.pyはスタンドアロンスクリプトでもインポート可能なモジュールでもかまいません。 tk.Tk
を継承するSimpleApp
でこれを試すと、余分な不要なウィンドウが表示されます。
トップレベルオブジェクトをTk
ではなくFrame
から継承するように設定することには利点があります。利点は、GUIに動的要素がある場合に発生します。 _textvariable=foo
_の代わりに_text= 'Label text'
_で内容を設定するLabel
.
この場合、_Tkinter.DoubleVar
_、_Tkinter.IntVar
_、および_Tkinter.StringVar
_オブジェクトを使用してデータを保持すると、これらのオブジェクトが設定されるたびにGUIが自動的に更新されるため、非常に役立ちます。ただし、これらのオブジェクトを使用するには、実行中のルートTkinter.Tk()
インスタンスとしてマスターを指定する必要があります。メインオブジェクトを明示的に_Tkinter.Tk,
_のサブクラスにしてからフレームとウィジェットを生成すると、Tk
インスタンスを渡して変数を適切に設定できるので、これは簡単です。
これはアイデアを説明する短いサンプルプログラムです。
_import Tkinter as tk
class Tkclass(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
app=Application(self)
app.master.title("Animal to Meat")
app.mainloop()
class Application(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.meatvar = tk.StringVar(master=parent)
self.meatvar.set("Meat?")
self.createWidgets()
def createWidgets(self):
top=self.winfo_toplevel()
top.rowconfigure(0, weight=1)
top.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
self.columnconfigure(3, weight=1)
self.cowButton = tk.Button(self, text='Cow', command=self.setBeef)
self.cowButton.grid(row=0,column=0)
self.pigButton = tk.Button(self, text='Pig',command=self.setPork)
self.pigButton.grid(row=0,column=1)
self.meatLabel = tk.Label(self)
self.meatLabel.configure(textvariable=self.meatvar)
self.meatLabel.grid(row=0,column=2)
self.quit = tk.Button(self, text='Quit',command=self.QuitApp)
self.quit.grid(row=0, column=3)
def setBeef(self):
self.meatvar.set("Beef")
def setPork(self):
self.meatvar.set("Pork")
def QuitApp(self):
top=self.winfo_toplevel()
top.quit()
main = Tkclass()
_