20

テスト UI の左上隅と右上隅にある 2 つのラベル ウィジェットを作成しようとしています。問題は、ウィジェットがくっついていて、それらの間にスペースが欲しいことです。

私の調査では、sticky、padx、および pady オプションを使用するための提案に出くわしました。しかし、 .grid() にどんな引数を渡しても、ウィジェット間にスペースを作成できないようです。2 つのウィジェット間の列と行の数に関係なく、行/列が空の場合、それらが存在しないかのようになり、ウィジェットがくっついて表示されることを理解しています。

.grid() メソッドを使用して、ウィジェットがくっつかないように配置するにはどうすればよいですか?

これまでの私のコードは次のとおりです。

#!/usr/bin/python
from Tkinter import *

class MyApp:
    def __init__(self, parent):
        self.myParent = parent
        self.main_container = Frame(parent)
        self.main_container.grid(row=0, rowspan=2, column=0, columnspan=4)

        self.top_frame = Frame(self.main_container)
        self.top_frame.grid(row=0, column=0, columnspan=4)

        self.top_left = Frame(self.top_frame)
        self.top_left.grid(row=0, column=0, columnspan=2)

        self.top_right = Frame(self.top_frame)
        self.top_right.grid(row=0, column=2, columnspan=2)

        self.bottom_frame = Frame(self.main_container)
        self.bottom_frame.grid(row=2, column=0, columnspan=4)

        self.top_left_label = Label(self.top_left, text="Top Left")
        self.top_left_label.grid(row=0, column=0, sticky='W', padx=2, pady=2)

        self.top_right_label = Label(self.top_right, text="Top Right")
        self.top_right_label.grid(row=0, column=4, sticky='E', padx=2, pady=2)

        self.text_box = Text(self.bottom_frame, height=5, width=40)
        self.text_box.grid(row=0, column=0)

root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()

〜〜アップデート〜〜

次のことを試しましたが、うまくいきませんでした:

    self.top_left = Frame(self.top_frame)
    self.top_left.grid(row=0, column=0, columnspan=2)
    for c in range(2):
        self.top_left.columnconfigure(c, weight=2)

    self.top_right = Frame(self.top_frame)
    self.top_right.grid(row=0, column=2, columnspan=2)
    for c in range(2):
        self.top_right.columnconfigure(c, weight=2)
4

5 に答える 5

71

grid_columnconfigure中央の列に重みを付けるために使用する必要があります。他の列よりも重量があるため、余分なスペースを埋めるために伸縮します。ただし、あなたの場合、実際にはグリッドを使用する必要はありません。packGUI のすべてが、より自然にフィットする特定の側面に沿って配置されます。

pack と grid の両方を使用する方法を示します。pack が最も簡単なので、最初に始めます。どうしても使用したい場合でもgrid、次のセクションを読んで、1 つの大きなレイアウトの問題を多くの小さなレイアウトの問題に分割する方法を理解してください。

分割統治

Tkinter でレイアウトを行う最善の方法は、「分割統治」です。最も外側のウィジェットから始めて、思いどおりにそれらを取得します。次に、これらのそれぞれに一度に取り組みます。

あなたの場合、最も外側のウィジェットが 1 つあります - メイン コンテナです。これはウィンドウ内の唯一のウィジェットであるため、pack はコンテナー全体を埋める最も簡単な方法です。grid も使用できますが、少し追加の作業が必要です。

self.main_container = Frame(parent. background="bisque")
self.main_container.pack(side="top", fill="both", expand=True)

一時的にフレームに独特の色を付けて、開発中に視覚化できるようにするのに役立ちます. 上記のコードを に追加し__init__てアプリを実行し、ウィンドウのサイズを変更して、メイン フレームが適切に拡大および縮小することを確認します。

次に、top_frame と bottom_frame の 2 つのフレームがあります。それらの名前と、グリッドを使用しようとした方法から判断すると、GUI を x 方向に埋める必要があると思います。また、上部のフレームはある種のツールバーであり、下部のフレームは GUI の実際の「メイン」部分であると推測しています。したがって、一番下のウィジェットがすべての余分なスペースを占めるようにしましょう。

これらは互いに積み重ねられているため、これもpack当然の選択です。次のコード (次のコードのみ) を追加して、これらの領域がウィンドウの予想される部分を占め、適切なサイズ変更動作を行うようにします。

    self.top_frame = Frame(self.main_container, background="green")
    self.bottom_frame = Frame(self.main_container, background="yellow")
    self.top_frame.pack(side="top", fill="x", expand=False)
    self.bottom_frame.pack(side="bottom", fill="both", expand=True)

次は、ラベルのフレームです。繰り返しになりますが、これらはコンテナーの端に沿ってスペースを占有するためpack、最も理にかなっています。繰り返しますが、次のコードを少しだけ追加してプログラムを実行し、ウィンドウのサイズが適切に変更され、ウィンドウの適切な部分に表示されることを確認してください。

    self.top_left = Frame(self.top_frame, background="pink")
    self.top_right = Frame(self.top_frame, background="blue")
    self.top_left.pack(side="left", fill="x", expand=True)
    self.top_right.pack(side="right", fill="x", expand=True)

次に、「コーナー」ラベルがあります。繰り返しますが、コンテナーは 1 行のウィジェットにすぎpackないため、簡単に行うことができます。隅にラベルが必要なのでsticky、それぞれに少し異なる属性を設定します。

    self.top_left_label = Label(self.top_left, text="Top Left")
    self.top_right_label = Label(self.top_right, text="Top Right")
    self.top_left_label.pack(side="left")
    self.top_right_label.pack(side="right")

最後に、テキスト ウィジェットがあります。それは下のフレーム全体を埋め尽くしpackます。

    self.text_box = Text(self.bottom_frame, height=5, width=40, background="gray")
    self.text_box.pack(side="top", fill="both", expand=True)

パックまたはグリッド?

元のコードにグリッドを使用し、それを修正する方法を尋ねました。例に pack を使用したのはなぜですか?

を使用するpackと、すべての構成オプションを 1 回の呼び出しでまとめることができます。ウィジェットをコンテナにgrid入れるだけでなく、適切にサイズ変更できるように、さまざまな列や行に「重み」を与えるように注意する必要があります。単にウィジェットを積み重ねたり、一列に並べたりするだけの場合は、packはるかに使いやすくなります。

私の GUI では、ほぼ常に と の組み合わせを使用していgridますpack。どちらも強力で、さまざまなことに優れています。覚えておくべき唯一のこと (これは重要です) は、同じ親でそれらを使用できないということです。コードを例として使用すると、同じ親を共有しているためpack、top_left フレームと top_right フレームには使用できません。ただし、同じアプリケーション内でそれらを混在させるgridことはできます。

もう一度、グリッドを使用して

わかりましたので、本当に を使いたいと思うかもしれませんgrid: これは学校の課題かもしれませんし、一度に 1 つのジオメトリ マネージャーに集中したいだけかもしれません。カッコいい。これが私がそれを行う方法です。繰り返しますが、分割して征服する必要があります。

まずはメインフレームから。メイン コンテナをパックする 1 つのステートメントを次の行に置き換えます。作成したフレームではなく、の行と列を構成する必要があることに注意してください。

    self.main_container.grid(row=0, column=0, sticky="nsew")
    self.myParent.grid_rowconfigure(0, weight=1)
    self.myParent.grid_columnconfigure(0, weight=1)

さて、上枠と下枠です。を削除しpack、次の行を追加します。まだ 1 列しかありませんが、今回は 2 行あります。重みが 1 になる行に注目してください。

    self.top_frame.grid(row=0, column=0, sticky="ew")
    self.bottom_frame.grid(row=1, column=0,sticky="nsew")
    self.main_container.grid_rowconfigure(1, weight=1)
    self.main_container.grid_columnconfigure(0, weight=1)

コーナー フレーム -- ついに、複数の列を持つコンテナーになりました。たるみをすべて埋めるために、真ん中に 3 番目の列を作成しましょう。pack「重み」が与えられていることに細心の注意を払いながら、ステートメントを次のように置き換えます。

    self.top_left.grid(row=0, column=0, sticky="w")
    self.top_right.grid(row=0, column=2, sticky="e")
    self.top_frame.grid_columnconfigure(1, weight=1)

次に、フレーム内のラベル。それらを拡張する必要がないため、デフォルトの重みをゼロのままにしておくことができます。両方のラベルが列 0 にあるのは奇妙に思えるかもしれません。それらは異なる親にあり、それらは親の唯一のウィジェットであるため、それぞれに 1 つの列しかないことに注意してください。

    self.top_left_label.grid(row=0, column=0, sticky="w")
    self.top_right_label.grid(row=0, column=0, sticky="e")

最後に、下のフレームにある唯一のウィジェットであるテキスト ウィジェットがあります。最後のpackステートメントを次のように置き換えます。

    self.text_box.grid(row=0, column=0, sticky="nsew")
    self.bottom_frame.grid_rowconfigure(0, weight=1)
    self.bottom_frame.grid_columnconfigure(0, weight=1)

結論

ウィジェットのレイアウトは簡単ですが、体系化する必要があります。自分が何をしているのかを考え、ウィジェットをグループに編成してから、一度に 1 つずつグループに取り組みます。これを行うと、どのジオメトリ マネージャーを使用する必要があるかが明らかになります。

ご覧のとおり、 にgridはさらに数行のコードが必要ですが、実際にグリッドがある場合は正しい選択です。あなたの場合、すでに GUI をセクションに細分化していたので、最終結果はグリッドでしたが、各セクションは別の上または下、または左端または右端に詰め込まれていました。このような場合、pack行と列の重みを気にする必要がないので、少し使いやすいです。

于 2013-02-19T00:12:11.667 に答える
1

遅刻しないよりはマシ ;)

Tkinter の「グリッド」は、すべてをまとめたいと考えています。そのため、セルをスキップできません。幅を指定してから、テキストを固定する必要があります。セルを表示しやすいように色を追加しました。BDをフレームに入れました。次に、グリッドがセルに重みを与えるように、左右のセルに幅を与える必要がありました。次にアンカー テキスト West または East。各セルに余分なスペースを 2 つ追加しなければならなかった理由はわかりませんが、フォントの問題であると考えました。

Rodasの方がクリーンでシンプルだと思いますが、あなたが求めているパラメータの範囲内に留まろうとしました.

小さなものの場合、パックはより簡単で高速です。

from tkinter import *

class MyApp:
    def __init__(self, parent):
        self.myParent = parent

        self.main_container = Frame(parent, bg="green")
        self.main_container.grid()

        self.top_frame = Frame(self.main_container)
        self.top_frame.grid()

        self.top_left = Frame(self.top_frame, bd=2)
        self.top_left.grid(row=0, column=0)

        self.top_right = Frame(self.top_frame, bd=2)
        self.top_right.grid(row=0, column=2)

        self.top_left_label = Label(self.top_left, bd=2, bg="red", text="Top Left", width=22, anchor=W)
        self.top_left_label.grid(row=0, column=0)

        self.top_right_label = Label(self.top_right, bd=2, bg="blue", text="Top Right", width=22, anchor=E)
        self.top_right_label.grid(row=0, column=0)

        self.bottom_frame = Frame(self.main_container, bd=2)
        self.bottom_frame.grid(row=2, column=0)

        self.text_box = Text(self.bottom_frame, width=40, height=5)
        self.text_box.grid(row=0, column=0)

root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()
于 2015-10-07T23:39:18.320 に答える
1

コンストラクターとコンストラクターのbg = "red"両方に追加すると、オプションを使用しても、コンストラクターが中心に固定されていることがわかります。それらに 1 つのウィジェットしか含まれない場合は、使用しないことをお勧めします。top_lefttop_rightFramessticky

#!/usr/bin/python
from Tkinter import *

class MyApp:
    def __init__(self, parent):
        self.top_left_label = Label(parent, text="Top Left")
        self.top_left_label.grid(row=0, column=0, padx=2, pady=2, sticky=N+S+W)

        self.top_right_label = Label(parent, text="Top Right")
        self.top_right_label.grid(row=0, column=1, padx=2, pady=2, sticky=N+S+E)

        self.text_box = Text(parent, height=5, width=40)
        self.text_box.grid(row=1, column=0, columnspan=2)

root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()
于 2013-02-19T00:12:22.723 に答える
1

これを行う簡単な方法は次のとおりです。

  • 最初に紙の上にGUIを設計するか、自分に合ったツールを使用してください
  • グリッド レイアウト マネージャーを使用する
  • 空のスペースを作成したい場合はいつでも、レイアウトの columnspan または rowspan プロパティを使用します。sticky プロパティの columnspan または rowspan を組み合わせて使用​​すると、グリッドの複数のセルを GUI コンポーネントに割り当てることができ、sticky プロパティを使用すると、その要素を強制的に貼り付けることができます。片面と反対側に空きスペースを残す
于 2015-07-16T18:32:57.217 に答える
0

GUI コンポーネントの配置を完全に制御する必要がある場合は、place レイアウトを試してください。高度に管理しやすいアプローチは、コンポーネントを複数のフレームに整理し、それぞれにグリッドまたはパック レイアウトを使用してから、それらのフレームすべてをプレース レイアウトを使用して整理することです。

于 2015-07-16T20:21:38.780 に答える