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

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

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

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

Python

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

Q&A

解決済

1回答

1646閲覧

Pytonでのウィンドウ表示

pikaka

総合スコア7

Tkinter

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

Python

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

0グッド

0クリップ

投稿2019/09/05 09:32

ヘディングのテキスト

前提・実現したいこと

pytonのtkinterを使用して、ウィンドウの表示、ボタンの配置を行いたいです。

発生している問題・エラーメッセージ

_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack

該当のソースコード

Python

1import tkinter as tk 2from tkinter import ttk 3 4class Window(tk.Frame): 5 def __init__(self, master, title, geometry,frame): 6 super().__init__(master) 7 self.pack() 8 master.geometry(geometry) 9 master.title(title) 10 master.resizable(0,0) 11 master.grid_columnconfigure(0, weight=1) 12 master.grid_rowconfigure(0, weight=1) 13 14 frame = ttk.Frame(master,style = 'TFrame',) 15 frame.grid(row=0, column=0, sticky='nwse') 16 frame.grid_columnconfigure((0, 1), weight=1) 17 frame.grid_rowconfigure((0, 1, 2, 3, 4), weight=1) 18 19 def Button(self,frame,button_name,text,width,x_position,y_position,action=None): 20 button_name = tk.Button(frame,text=text, width=width) 21 button_name.place(x=x_position,y=y_position) 22 if action==quit: 23 def close(a): 24 self.quit() 25 button_name.bind("<Button-1>", close) 26 27def main(): 28 pokeda = tk.Tk() 29 pokeda = Window(pokeda,"ポケ打","400x300","frame1") 30 pokeda.Button("frame1","a","たたかう",10,100,150) 31 pokeda.Button("frame1","b","にげる",10,200,150,quit) 32 pokeda.mainloop() 33 34 35if __name__ == "__main__": 36 main()

試したこと

frameを使用する前までは実行できていたのですが、小回りを利かせるために使用したところ上記のエラーがでました。エラーの意味は理解できますが、理由がどうしてもわかりません。

補足情報(FW/ツールのバージョンなど)

まだプログラミングを初めて一週間にも満たないため、とんちんかんなことを言っている(している)、かもしれませんがどうかご容赦ください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

問題がいろいろとありすぎて・・とりあえず順番に説明します。。。。。。。

現在やろうとしていることを整理すると、

  • ToplevelWindow 上に Frame を配置する(1)
  • Window class は Frmae を継承しているので、基本的に Frame として扱われる(2)
  • Frame の上に Button を配置する(3)

となります。
また、基本的なこととして

  • Tkにて部品の配置はレイアウトマネージャを使用する
  • レイアウトマネージャは pack / grid / place の3種類がある
  • 各WidowやFrameで使用するレイアウトマネージャーは1つに限定するのが望ましい(4)

を覚えておいてください。

で、ソースコードを見てみると ``init()` 関数内に

Python

1self.pack()

の記述がありますので、(1)の ToplevelWindow 上に Frame を配置するためのレイアウトマネージャーは pack を使用しているのがわかります。
ですので、その後にある grid マネージャー用の制御命令

Python

1master.grid_columnconfigure(0, weight=1) 2master.grid_rowconfigure(0, weight=1)

は全く意味をなさないので不要です。

また(2)に記述したとおり、Windowクラス自体を Frame として扱うので、そのあとの処理で

Python

1frame = ttk.Frame(master,style = 'TFrame',) 2frame.grid(row=0, column=0, sticky='nwse') 3frame.grid_columnconfigure((0, 1), weight=1) 4frame.grid_rowconfigure((0, 1, 2, 3, 4), weight=1)

として、わざわざもう一つのFrameのインスタンスを生成しているのは全く意味不明です。
これをやりたいのであれば self を使って

Python

1self.grid(row=0, column=0, sticky='nwse') 2self.grid_columnconfigure((0, 1), weight=1) 3self.grid_rowconfigure((0, 1, 2, 3, 4), weight=1)

とすると良いことになります。・・・更にが、Button() 関数をみると
(3) のFrame の上への Button を配置する処理の記述として

Python

1button_name.place(x=x_position,y=y_position)

があり レイアウトマネージャーは place を使用しているのがわかりますので
そもそも __init__() 関数内の

Python

1frame.grid(row=0, column=0, sticky='nwse') 2frame.grid_columnconfigure((0, 1), weight=1) 3frame.grid_rowconfigure((0, 1, 2, 3, 4), weight=1)

も grid マネージャー用の制御命令ですので不要となります。

次に Button() 関数内の

Python

1button_name = tk.Button(frame,text=text, width=width)

の処理ですが、上で述べたように(2)によりWindowクラス自体(self) が Frameですので

Python

1button_name = tk.Button(self,text=text, width=width)

となります

これで、エラーはでなくなるのですが、残念ながら(1)の配置において、Frameのサイズが確定されずに小さく表示されてしまう為、Buttonが見えない状態となってしまいます。
ですので、FrameをToplevelWindowのサイズいっぱいまで広げて表示するように fillパラメータとexpand パラメータを追加して

self.pack(fill=tk.BOTH, expand=1)

のようにしてください。

一応これで説明終わり

以上、これらを修正して

import tkinter as tk from tkinter import ttk class Window(tk.Frame): def __init__(self, master, title, geometry,frame): super().__init__(master) self.pack(fill=tk.BOTH, expand=1) master.geometry(geometry) master.title(title) master.resizable(0,0) def Button(self,frame,button_name,text,width,x_position,y_position,action=None): button_name = tk.Button(self,text=text, width=width) button_name.place(x=x_position,y=y_position) if action==quit: def close(a): self.quit() button_name.bind("<Button-1>", close) def main(): root = tk.Tk() pokeda = Window(root,"ポケ打","400x300","frame1") pokeda.Button("frame1","a","たたかう",10,100,150) pokeda.Button("frame1","b","にげる",10,200,150,quit) root.mainloop() if __name__ == "__main__": main()

にてとりあえず動作するのではないでしょうか。

投稿2019/09/05 11:09

編集2019/09/05 11:13
magichan

総合スコア15898

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

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

pikaka

2019/09/06 05:12

とても丁寧な回答ありがとうございます!順を追った説明でかなり理解度が上がりました。助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問