Tkinterを使用して1つのフレーム内に複数のフレームをネストしようとしています。オブジェクト指向でこれを実現するにはどうすればよいですか?

ブルーデイズ

私のコードは基本的にこれを行います:

私の問題

これは明らかに私が試したいことではありません。さらに明確にするために、ウィンドウを次のように表示します。

理想的なソリューション

from tkinter import *
import tkinter as tk
from tkinter import ttk

root = tk.Tk()

class Encoding(tk.Tk):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.mode = StringVar()
##      If I remove the next line it breaks it entirely.
        self.encoding_frame = ttk.Frame(parent)
        self.encrypt = ttk.Radiobutton(self.encoding_frame, text='Encrypt', variable=self.mode, value='encrypt')
        self.decrypt = ttk.Radiobutton(self.encoding_frame, text='Decrypt', variable=self.mode, value='decrypt')
        self.encrypt.grid(column=0, row=0, ipadx=2, sticky=W)
        self.decrypt.grid(column=0, row=1, ipadx=2, sticky=W)
        self.encoding_frame.grid(column=0, columnspan=3, row=2, sticky=S)


class MainApplication(tk.Frame, Encoding):
    # Create a main frame here.
    # Would like frames to be nested within this frame. This seems redundant but nesting with a main
    # frame allows for consistent themes, and gives additional control of layout between subframes.
    # Inheritance is confusing.
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.main_frame = ttk.LabelFrame(parent, text="Main Window", width=500, height=500)
        self.main_frame['borderwidth'] = 3
        self.main_frame['relief'] = 'raised'
        self.main_frame.grid(column=0, row=0)
        self.encoding = Encoding(self)
##      I wrote the following line hoping that I could have main_frame become the parent frame.
        self.encoding.encoding_frame = ttk.LabelFrame(self.main_frame)


if __name__ == "__main__":
    app = MainApplication(root)
    root.mainloop()

私は明らかに何かが正しくない。私がプログラムを書き直した理由は、オブジェクト指向コードについての理解と自信を深めるためです。私はこれでより良い洞察を得ることができることを望んでいるので、どんな助けも素晴らしいでしょう。

ブライアン・オークリー

コードで起こっているいくつかの問題があります。

おそらく最大の問題は、あるEncodingから継承tk.TkMainApplicationから継承するtk.Frame Encoding(そのルートウィンドウとフレームの両方を行う)、その後MainApplicationのインスタンスを作成しますEncodingさらに、の別のインスタンスを明示的に作成してtk.Tk()、2つのルートウィンドウを作成します。それはすべて解きほぐされる必要があります。

継承は isa 関係を作成しますあなたMainApplicationから継承することによって、EncodingそれMainApplicationEncodingオブジェクトであると言ってます。これはコードには当てはまりません。Encodingオブジェクトはアプリケーションのごく一部のみを表します。そのためには継承はなく構成が必要ですつまりオブジェクトがあります。MainApplication Encoding

したがって、最初のステップは、EncodingからMainApplication継承するクラスのリストから削除することです。

おそらく削除できるもう1つのものはself.encoding_frameです。MainApplicationそれ自体がフレームなので、持っている理由はわかりません代わりに、ではなくMainApplicationから継承します。ttk.LabelFrametk.Frame

最後に、MainApplicationcreatesなのでEncoding、の呼び出しgridまたはpackインスタンスでの責任を負う必要がありますEncoding

全体として、MainApplicationこれに削減することができます:

class MainApplication(ttk.LabelFrame):
    def __init__(self, parent, *args, **kwargs):
        ttk.LabelFrame.__init__(self, parent, *args, **kwargs)

        self.configure(text="Main Window")
        self['borderwidth'] = 3
        self['relief'] = 'raised'

        self.encoding = Encoding(self)
        self.encoding.grid(row=0, column=0, sticky="ew")

これは100%完全ではありませんが、開始するのに適した場所です。あなたのイメージに基づいて、メインアプリケーションの他の部分(メッセージウィジェット、キーウィジェット、および文字起こしウィンドウ)用の他のクラスがあると思います。

についてEncodingは、同じアドバイスの多くが当てはまります。これはアプリケーションの一部にすぎないため、から継承しないでくださいtk.Tk代わりに、オブジェクト自体がすでにフレームであるため、継承してからttk.Frame削除することができますself.encoding_frameEncoding

これらの変更によりEncoding、次のようになります。ラジオボタンがself親としてどのようになっているかに注目してください適切なオブジェクトを作成している場合、クラス内のすべてのウィジェットは、クラス自体またはその子孫の1つの子である必要があります。このようなクラスは、parentそれ自体以外には何も入れてはなりません

class Encoding(ttk.Frame):
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)

        self.mode = StringVar()
        self.encrypt = ttk.Radiobutton(self, text='Encrypt', variable=self.mode, value='encrypt')
        self.decrypt = ttk.Radiobutton(self, text='Decrypt', variable=self.mode, value='decrypt')

        self.encrypt.grid(column=0, row=0, ipadx=2, sticky=W)
        self.decrypt.grid(column=0, row=1, ipadx=2, sticky=W)

最後に、以降は、MainApplication代わりに継承の-今のフレームであるEncodingから、その継承tk.Tkのインスタンスを作成するコードのブロック-MainApplication呼び出しを担当する必要があるのpackか、gridMainApplicationはルートウィンドウ内に直接ある唯一のウィジェットであるためpack、ウィンドウのサイズが変更されたときに適切な動作を実現するために行と列の重みを設定することを覚えておく必要がないため、これが最良の選択です。

また、rootプログラムの最初ではなく、同じブロックで作成することをお勧めします。

コードの一番下のブロックは次のようになります。

if __name__ == "__main__":
    root = tk.Tk()
    app = MainApplication(root)
    app.pack(fill="both", expand=True)
    root.mainloop()

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ