質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5737閲覧

Python(TkInter) 希望のデザインを達成するため、Widgetを貼付けていきたいが PACK・GRID・PLACEの使い方がよく分からない

saya24

総合スコア247

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/05/07 02:21

編集2020/05/07 02:23

【一つのframe】の上で 以下のようなデザインを達成したいのですが、そもそも
①PACKとGRIDを使い分けることができるのか、一度PACKを使いだしたら 同frame内では PACKの利用に統一しなければいけないのか?
②GRIDのrowとcolumnの考え方も、1あたりのメッシュを認識できていないのに どうやって位置を決定づけられるのだろう??
と疑問を抱いています。

frame

1行目に左詰めで、2つのwidgetを並べて貼り付け、
2行目では一つのwidgetを横いっぱいに配置
3行目も 一つのwidgetを横いっぱいに配置

少し空白行をあけて....

再度別の一つのwidgetを横いっぱいにに配置
その直下に 2つのwidgetを左詰めで並べて配置
その直下で 2つのwidgetを右詰めで並べて配置

ということを達成したいのですが、どういう貼付け方を行うべきでしょうか?

ひょっとして1つのframeでは 無理でしょうか??

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

(1) PACKとGRIDを使い分けることができるのか、

一度PACKを使いだしたら 同frame内では PACKの利用に統一しなければいけないのか?

間に frame を挟むことで使い分けは可能です。

同frame内に PACKとGRID は混在できないので、統一する必要がありますが、
階層が異なる場合、例えばPACKで配置した子frame内でGRIDを使うことは可能です。

PLACE はこの制限を受けません。

(2) GRIDのrowとcolumnの考え方も、1あたりのメッシュを認識できていないのに

どうやって位置を決定づけられるのだろう??

座標指定が、ピクセル単位の(x,y)ではなくセル単位(row,column) となる。
各セルの width, height は、それぞれの行・列に配置されたウィジェットのうち
最大のモノが適応される…と考えると解りやすいのではないでしょうか。


1つのフレームという事で、実際にgrid を使って説明します。
(packの方が管理はしやすいのですが、「横に並べる」時にフレームを使います)

イメージ説明

1行目に左詰めで、2つのwidgetを並べて貼り付け、

column を順に指定します。

2行目では一つのwidgetを横いっぱいに配置
3行目も 一つのwidgetを横いっぱいに配置

columnspan で横セルを結合します。
また rowconfigure と sticky=tk.NSWE でリサイズ時に最大化するように指定

少し空白行をあけて....

ttk.Separator 等がありますが、空のラベルを入れました。(ソース後述)

再度別の一つのwidgetを横いっぱいにに配置

2,3 行目と同じ。

その直下に 2つのwidgetを左詰めで並べて配置

1行目と同じ。

その直下で 2つのwidgetを右詰めで並べて配置

右詰めで column を指定します。


※ 説明の為に、row, column の表を作りましたが、
この様に管理するのはお勧めしません。
row, column 追加があった際の保守性が悪くなります。

回避策はソースコード内で説明しますが、
極力 rowやcolumn の指定にマジックナンバーを使わない事です。


イメージ説明

python

1from types import SimpleNamespace 2import tkinter as tk 3from tkinter import ttk 4from tkinter.scrolledtext import ScrolledText 5 6 7def create_view(root): 8 parent = ttk.Frame(root, style="parent.TFrame") 9 10 labelA = ttk.Label(parent, text="Label", width=20, style="a.TLabel") 11 labelB = ttk.Label(parent, text="ListBox?", width=20, style="b.TLabel") 12 labelC = ttk.Label(parent, text="Label", width=20, style="c.TLabel") 13 14 buttonA = ttk.Button(parent, text="Button") 15 buttonB = ttk.Button(parent, text="Button") 16 buttonC = ttk.Button(parent, text="Button") 17 buttonD = ttk.Button(parent, text="Quit", command=root.destroy) 18 19 separator = ttk.Label(parent, style="a.TLabel") # As blank vertical space 20 21 text = ScrolledText(parent, height=10) 22 text.insert(tk.END, "ScrolledText") 23 message = tk.Message(parent, text="Message ....", width=200) 24 25 # NOTE: export all local variables 26 return SimpleNamespace(**locals()) 27 28 29def init_view_style(view): 30 # style config 31 bgcolor = "#dde7ee" 32 bgcolor2 = "#9bc2e6" 33 fgcolor = "yellow" 34 font = ("", 10, "bold") 35 36 # Style non-ttk widgets 37 view.root.configure(bg=bgcolor) 38 view.text.config(insertbackground="white", bg="black", fg=fgcolor, borderwidth=0, font=font) 39 view.message.configure(fg=fgcolor, bg=bgcolor2, font=font) 40 41 # ttk widgets style 42 style = ttk.Style(view.root) 43 style.configure("TLabel", font=("", 10, "bold"), anchor="c") 44 style.configure("a.TLabel", background=bgcolor) 45 style.configure("b.TLabel", background="black", foreground=fgcolor) 46 style.configure("c.TLabel", background=bgcolor2, foreground=fgcolor) 47 style.configure("TButton", background=bgcolor) 48 style.configure("parent.TFrame", background=bgcolor) 49 50 51def init_view_layout(view): 52 # Grid Layout を使う時の Tips 53 54 # 行毎にレイアウトを呼ぶ出す部分を関数化し 55 # デコレーターによりリスト `rows` に入れます。 56 # 後でまとめて、順番に行番号 `row` を与えて呼び出します。 57 58 # これにより、行の入れ替えや追加が容易に管理できるようになります。 59 60 from itertools import count 61 from functools import partial 62 63 rows = [] 64 addrow = rows.append 65 maxcolumn = 6 66 right = lambda column: maxcolumn-column-1 67 nopad = {"padx":0, "pady": 0} 68 69 def _finish_layout(): 70 for row, func in enumerate(rows): 71 func(row, partial(next, count()), **nopad) 72 73 parent = view.parent 74 parent.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) 75 parent.grid_columnconfigure(2, weight=True) 76 77 @addrow 78 def row_header(row, col, **kw): 79 view.labelA.grid(row=row, column=col(), **kw) 80 view.labelB.grid(row=row, column=col(), **kw) 81 82 @addrow 83 def row_scrolledtext(row, col, **kw): 84 view.text.grid(row=row, column=col(), columnspan=maxcolumn, sticky=tk.NSEW, **kw) 85 parent.grid_rowconfigure(row, weight=True) 86 87 @addrow 88 def row_center_button(row, col, **kw): 89 view.buttonA.grid(row=row, column=col(), columnspan=maxcolumn) 90 91 @addrow 92 def row_blank_separator(row, col, **kw): 93 view.separator.grid(row=row, column=col(), sticky=tk.NSEW, **kw) 94 95 @addrow 96 def row_message(row, col, **kw): 97 view.message.grid(row=row, column=col(), columnspan=maxcolumn, sticky=tk.NSEW, **kw) 98 parent.grid_rowconfigure(row, weight=True) 99 100 @addrow 101 def row_bottom_label(row, col, **kw): 102 view.buttonB.grid(row=row, column=col(), sticky=tk.NSEW, **kw) 103 view.labelC.grid(row=row, column=col(), sticky=tk.NSEW, **kw) 104 105 @addrow 106 def row_footer(row, col, **kw): 107 view.buttonD.grid(row=row, column=right(col()), sticky=tk.NSEW, **kw) 108 view.buttonC.grid(row=row, column=right(col()), sticky=tk.NSEW, **kw) 109 110 _finish_layout() 111 112 113def main(): 114 root = tk.Tk() 115 root.title("grid layout demo") 116 view = create_view(root) 117 init_view_style(view) 118 init_view_layout(view) 119 root.mainloop() 120 121 122if __name__ == '__main__': 123 main() 124

init_view_style(view) の行をコメントアウトすると、スタイル適応なしで実行されます。

イメージ説明


追記: packでの実装例

最小限のコードになりますが、簡単な方法では、
「横に並べる」部分だけを別フレームに切り出し、
side="left" を指定して横並びにします。

python

1import tkinter as tk 2from tkinter import ttk 3from tkinter.scrolledtext import ScrolledText 4 5 6def main(): 7 root = tk.Tk() 8 9 frameA = ttk.Frame(root) 10 frameA.pack(fill=tk.BOTH) 11 ttk.Label(frameA, text="Label", width=10).pack(side=tk.LEFT) 12 ttk.Label(frameA, text="ListBox?", width=10).pack(side=tk.LEFT) 13 14 text = ScrolledText(root, height=10) 15 text.pack(fill=tk.BOTH, expand=1) 16 text.insert(tk.END, "ScrolledText") 17 18 ttk.Button(root, text="Button").pack() 19 ttk.Label(root).pack() 20 tk.Message(root, text="Message", width=200, bg="black", fg="white").pack(fill=tk.BOTH, expand=1) 21 22 frameB = ttk.Frame(root) 23 frameB.pack(fill=tk.BOTH) 24 ttk.Button(frameB, text="Button", width=10).pack(side=tk.LEFT) 25 ttk.Label(frameB, text="Label", width=10).pack(side=tk.LEFT) 26 27 ttk.Button(root, text="Quit", command=root.destroy).pack(side=tk.RIGHT) 28 ttk.Button(root, text="Button").pack(side=tk.RIGHT) 29 30 root.mainloop() 31 32 33if __name__ == '__main__': 34 main() 35

投稿2020/05/07 08:06

編集2020/05/07 10:21
teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

magichan

2020/05/07 08:29

全く同じタイミングで同じような投稿とは・・運命を感じますね!(嘘)
teamikl

2020/05/07 09:46 編集

投稿前にリロードしたのですが、誤って送信してしまったのかと焦りました(笑) そして、magichanさんの画像を見て、自分のcolumn 2, 3 は冗長だったかなと気が付いたのですが、 将来あるかもしれない列の追加に備えて、余らせておくのもありかなとも考えたり。 gridは使いづらいと思ってたのですが、収穫がありました。
saya24

2020/05/07 08:52

丁寧な説明誠にありがとうございます。 ちょっとじっくりみさせてください。ようやく理解出来そうです。 まずはお礼まで
guest

0

ベストアンサー


YES:LayoutManagerは同じマスターウィンドウ上でミックスするべきではありません。

下記のようにExcel上でレイアウトを構築するイメージです。
・それぞれの行・列の幅をどうするか
・スペースをどうするか
は後から構いませんので、とりあえずはどの行・列にWidgetを配置するかだけを考えると良いかと思います。

イメージ説明

上記のレイアウトが決まれば、
1.Widgetの widthパラメータを設定することで、それぞれ列の幅を設定する
2.スペースが必用な箇所のgrid()のパラメータに padx,padyを渡す
3.Windowサイズに変更が生じた際に変更される行・列をgrid_rowconfigure(),grid_columnconfigure()weight パラメータで設定する
4.Windowサイズに変更が生じ、行・列の幅が変更された際に Widgetの挙動を grid()stickyパラメータで設定する

あたりでそれっぽい挙動になるのではないでしょうか

Python

1import tkinter as tk 2 3root = tk.Tk() 4label1 = tk.Label(root, text='Label', width=10) 5label1.grid(row=0, column=0) 6listbox = tk.Listbox(root, height=1, width=10) 7listbox.grid(row=0, column=1) 8text1 = tk.Text(root) 9text1.grid(row=1, column=0, columnspan=5, sticky=tk.W+tk.E) 10button1 = tk.Button(root, text='Button', width=10) 11button1.grid(row=2, column=2, padx=20, pady=(0, 20)) 12text2 = tk.Text(root) 13text2.grid(row=3, column=0, columnspan=5, sticky=tk.W+tk.E) 14button2 = tk.Button(root, text='Button', width=10) 15button2.grid(row=4, column=0) 16label2 = tk.Label(root, text='Label', width=10) 17label2.grid(row=4, column=1) 18button3 = tk.Button(root, text='Button', width=10) 19button3.grid(row=5, column=3) 20button4 = tk.Button(root, text='Button', width=10) 21button4.grid(row=5, column=4) 22 23root.grid_rowconfigure(1, weight=1) 24root.grid_rowconfigure(3, weight=1) 25root.grid_columnconfigure(2, weight=1) 26 27root.mainloop()

イメージ説明

投稿2020/05/07 08:06

編集2020/05/08 01:25
magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saya24

2020/05/07 08:55

ありがとうございます。非常に分かりやすいです。 実装後に報告を改めさせてください。まずはお礼まで
saya24

2020/05/08 03:59

改めてありがとうございました。今の私のレベルに本当にちょうど良いでレベルで 実際少々の変更を加えながら 今後に生かせるような回答となっておりました。 また何かの機会でご支援を頂けたら幸いです、重ねてお礼を申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問