web-dev-qa-db-ja.com

Tk()の呼び出しは実際に何をしますか?

NMT Tkinter 8.5リファレンス の最小限の例を見たとき、私はTkinterをブラッシュアップしていました。

_#!/usr/bin/env python
import tkinter as tk

class Application(tk.Frame):    
    def __init__(self, master=None):    
        tk.Frame.__init__(self, master)
        self.grid()
        self.createWidgets()

    def createWidgets(self):    
        self.quitButton = tk.Button(self, text='Quit',command=self.quit)
        self.quitButton.grid()

app = Application()
app.master.title('Sample application')
app.mainloop()
_

Tkクラスが初期化されていないことに気付くまでは、すべて問題ありません。私が見つけた他のオンラインリファレンス資料( Pythonのライブラリリファレンスeffbot.orgTkDocs )では、通常、root = tk.Tk()、これから残りの例が構築されます。また、NMTの参照のどこにも、Tkクラスの初期化への参照はありませんでした。

Tkクラスに関して私が得ることができる情報もあいまいで、Pythonリファレンスはそれを「トップレベルウィジェット...通常はメインウィンドウである」としてのみリストしています。最後に、前に示したスニペットの最後の行を置き換えると、次のようになります。

_root = tk.Tk()
app = Application(root)
_

プログラムは以前と同じように実行されます。これらすべてを念頭に置いて、私が知りたいのは次のとおりです。

  • root = tk.Tk()の呼び出しは実際に何をしますか(初期化されるもののように)、なぜ前のスニペットはそれなしで機能するのですか?
  • Tk()を呼び出さず、Frameクラスを中心にアプリケーションを構築した場合、落とし穴や制限が発生しますか?
10

Tkinterは、内部でtcl/tkインタープリターを起動し、tkinterコマンドをtcl/tkコマンドに変換することで機能します。メインウィンドウとこのインタープリターは本質的にリンクされており、tkinterアプリケーションが機能するには両方が必要です。

Tkのインスタンスを作成すると、このインタープリターが初期化され、ルートウィンドウが作成されます。明示的に初期化しない場合、最初のウィジェットを作成するときに暗黙的に作成されます。

自分で初期化しないことによる落とし穴はないと思いますが、pythonの禅が述べているように、「明示的は暗黙的よりも優れています」。コードを理解するのは少し簡単です。 Tkのインスタンスを明示的に作成します。これにより、たとえば、他の人があなたのコードについて、この他のコードについて尋ねたのと同じ質問をするのを防ぐことができます。

13
Bryan Oakley

Bryan Oakley's 答えは的確です。ウィジェットを作成すると、暗黙的にtcl/tkインタープリターのインスタンスが作成されます。ただし、Tkが暗黙的に作成される方法をよりよく理解するために、いくつかのコードを追加したいと思います。

ウィジェットオブジェクトが作成されるたびに(フレーム、ボタン、またはttkベースのウィジェットであるかどうかに関係なく)、BaseWidgetクラスの___init___メソッドが呼び出され、次に__setup_ 方法。関連する部分の抜粋は次のとおりです。

_def _setup(self, master, cnf):
    """Internal function. Sets up information about children."""
    if _support_default_root:
        global _default_root
        if not master:
            if not _default_root:
                _default_root = Tk()
            master = _default_root
    self.master = master
    self.tk = master.tk
_

__support_default_root_と__default_root_はどちらもグローバル変数であり、tkinterパッケージの___init__.py_ファイルの132〜133行で宣言されています。これらは次の値に初期化されます。

__support_default_root = 1
_default_root = None
_

これは、masterが提供されておらず、インタープリターがまだ作成されていない場合、Tkのインスタンスが作成され、将来のすべてのウィジェットのデフォルトルートとして割り当てられることを意味します。

Tkクラスのインスタンスを作成するときにも興味深いことがあります。次のスニペットは、_Tk._loadtk_メソッドからのものです。

_if _support_default_root and not _default_root:
    _default_root = self
_

つまり、Tkクラスの初期化方法に関係なく、常にデフォルトのルートとして設定されます。

4