web-dev-qa-db-ja.com

フレームとグリッドを使用したtkinter GUIレイアウト

guiレイアウト

gui layout

私が期待するもの のようなほとんど何も見えません

what I expect

そのため、私には理解できない基本事項があると思います。

フレームには独自の「グリッドスペース」(行、列)が含まれていると仮定しましたが、私が見る動作はそれを支持せず、トップフレームに必要な方法で物事を動作させることに途方に暮れています。私のラベルは、フレーム全体にまたがる「フレームラベル」の下の同じ行LからRにあることになっています-そうでないことを除いて。実際のjpgを目標jpgのように見せたいので、グリッドを使用してそれを行いたいです。

緑色のフレームの右側にある入力フィールドの1つを見ることができます。なぜそこに行くのですか?

from Tkinter import *

root = Tk()
root.title('Model Definition')
root.resizable(width=FALSE, height=FALSE)
root.geometry('{}x{}'.format(460, 350))

top_frame = Frame(root, bg='cyan', width = 450, height=50, pady=3).grid(row=0, columnspan=3)
Label(top_frame, text = 'Model Dimensions').grid(row = 0, columnspan = 3)
Label(top_frame, text = 'Width:').grid(row = 1, column = 0)
Label(top_frame, text = 'Length:').grid(row = 1, column = 2)
entry_W = Entry(top_frame).grid(row = 1, column = 1)
entry_L = Entry(top_frame).grid(row = 1, column = 3)
#Label(top_frame, text = '').grid(row = 2, column = 2)

center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3).grid(row=1, columnspan=3)
ctr_left = Frame(center, bg='blue', width=100, height=190).grid(column = 0, row = 1, rowspan = 2)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3).grid(column = 1, row=1, rowspan=2)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3).grid(column = 2, row=1, rowspan=2)

btm_frame = Frame(root, bg='white', width = 450, height = 45, pady=3).grid(row = 3, columnspan = 3)
btm_frame2 = Frame(root, bg='lavender', width = 450, height = 60, pady=3).grid(row = 4, columnspan = 3)


root.mainloop()

具体的には、ラベルとエントリウィジェットはどこに行き、どのようにしてそれらを目標に近づけるのか(トップフレーム、残りは後で説明します)。

20
shawn

フレームには独自の「グリッド空間」が含まれていると仮定しました

それは正しい仮定です。

緑色のフレームの右側にある入力フィールドの1つを見ることができます。なぜそこに行くのですか?

問題はここから始まります。

_top_frame = Frame(root, ...).grid(row=0, ...)
_

Pythonでは、x = y().z()は常にx.z()の結果に設定します。 top_frame = Frame(...).grid(...)の場合、grid(...)は常にNoneを返すため、_top_frame_はNoneになります。これにより、トップフレームに入ると思われるすべてのウィジェットが実際にルートウィンドウに移動します。

ソリューションの概要

一般的な経験則として、neverの一部としてgridpack、またはplaceを呼び出す必要があります。ウィジェットを作成する同じステートメントの。部分的にはあなたが経験しているこの正確な振る舞いのためですが、それはまたあなたのコードを書くことを難しくし、長期にわたって維持することを難しくするからです。

ウィジェットの作成とウィジェットのレイアウトは、2つの異なるものです。私の経験では、レイアウトの問題は、かなり()レイアウトコマンドをグループ化するとデバッグしやすくなります。

また、グリッドを使用するときは一貫性を保ち、オプションを常に同じ順序で配置して、レイアウトをより簡単に視覚化できるようにする必要があります。最後に、gridを使用するときは、常にstickyオプションを指定する習慣をつけ、フレームを含むそれぞれの行と列に常にゼロ以外の重みを与える必要があります。

ソリューション例

コードを作成する方法は次のとおりです。はるかに長くなりますが、理解しやすくなります。

_from Tkinter import *

root = Tk()
root.title('Model Definition')
root.geometry('{}x{}'.format(460, 350))

# create all of the main containers
top_frame = Frame(root, bg='cyan', width=450, height=50, pady=3)
center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3)
btm_frame = Frame(root, bg='white', width=450, height=45, pady=3)
btm_frame2 = Frame(root, bg='lavender', width=450, height=60, pady=3)

# layout all of the main containers
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)

top_frame.grid(row=0, sticky="ew")
center.grid(row=1, sticky="nsew")
btm_frame.grid(row=3, sticky="ew")
btm_frame2.grid(row=4, sticky="ew")

# create the widgets for the top frame
model_label = Label(top_frame, text='Model Dimensions')
width_label = Label(top_frame, text='Width:')
length_label = Label(top_frame, text='Length:')
entry_W = Entry(top_frame, background="pink")
entry_L = Entry(top_frame, background="orange")

# layout the widgets in the top frame
model_label.grid(row=0, columnspan=3)
width_label.grid(row=1, column=0)
length_label.grid(row=1, column=2)
entry_W.grid(row=1, column=1)
entry_L.grid(row=1, column=3)

# create the center widgets
center.grid_rowconfigure(0, weight=1)
center.grid_columnconfigure(1, weight=1)

ctr_left = Frame(center, bg='blue', width=100, height=190)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3)

ctr_left.grid(row=0, column=0, sticky="ns")
ctr_mid.grid(row=0, column=1, sticky="nsew")
ctr_right.grid(row=0, column=2, sticky="ns")

root.mainloop()
_

結果:

screenshot of running example

35
Bryan Oakley

variable = Widget(...).grid()は、grid()/pack()/place()Noneを返すため、Noneを変数に割り当てます。

つかいます

variable = Widget(...)
variable.grid() # .pack() .place()
2
furas