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

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

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

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

Q&A

2回答

2337閲覧

For文を使ってTkinterのTextを変更したい

Rintaco

総合スコア0

Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

0グッド

1クリップ

投稿2020/05/02 03:06

前提・実現したいこと

Python学習のためPythonとTkinterを使ってナンバープレース(数独)というパズルを解くシステムを作っています。
For文で9×9マスのgame_frameを作り、そこに数値を表示したいのですが、どうしても表示してくれません。
完成イメージ

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

表示してくれない・・・
以下のソースコードの”frame_list[i]~”辺りが、完全に勘違いしている気がします。

Python

1 2def gom(): 3 global frame_list 4 global numpla_list 5 for i in range(81): 6 frame_list[i] = Label(game_frame, text = numpla_list[i][0], bg = 'LightGray') 7 print(numpla_list[i][0]) 8

該当のソースコード

Python

1from tkinter import * 2 3#### Call関数定義 #### 4def fim1(): 5 print("新規(N)") 6 7def fim2(): #暫定的にとりあえずサンプルを入れる 8 global numpla_list 9 for i in range(81): 10 numpla_list[i][0] = sample_list[i] 11 12def fim3(): 13 print("保存(S)") 14 15def gom(): 16 global frame_list 17 global numpla_list 18 for i in range(81): 19 frame_list[i] = Label(game_frame, text = numpla_list[i][0], bg = 'LightGray') 20 print(numpla_list[i][0]) 21 22 23def hem(): 24 print("ヘルプ") 25 26if __name__ == '__main__': 27 28 root = Tk() 29 30 menubar = Menu(root) 31 #### File menu #### 32 filemenu = Menu(menubar,tearoff=0) 33 filemenu.add_command(label='新規(N)', command = fim1) 34 filemenu.add_command(label='開く(O)', command = fim2) 35 filemenu.add_command(label='保存(S)', command = fim3) 36 filemenu.add_separator() 37 filemenu.add_command(label='終了(X)', command = quit) 38 39 #### Go Menu #### 40 gomenu = Menu(menubar,tearoff=0) 41 gomenu.add_command(label='実行(U)', command = gom) 42 43 #### Help Menu #### 44 helpmenu = Menu(menubar, tearoff=0) 45 helpmenu.add_command(label="ヘルプ(H)", command = hem) 46 47 #### メインメニュー #### 48 menubar.add_cascade(label="ファイル(F)", menu = filemenu) 49 menubar.add_cascade(label="実行(U)", menu = gomenu) 50 menubar.add_cascade(label="ヘルプ(H)", menu = helpmenu) 51 52 53 root.config(menu=menubar) 54 55 root.title("ナンバープレース") 56 root.minsize(300,300) 57 root.rowconfigure(0,weight=1) 58 root.columnconfigure(0,weight=1) 59 root.grid() 60 61 ###フレームオブジェクト作成### 62 root_frame = Frame(root, relief='groove', borderwidth=5, bg='LightGray') 63 status_frame = Frame(root_frame, height=50, relief='sunken', borderwidth=3, bg='LightGray') 64 game_frame = Frame(root_frame, relief='sunken', borderwidth=3, bg='LightGray') 65 root_frame.pack() 66 status_frame.pack(pady=5, padx=5, fill='x') 67 game_frame.pack(pady=5, padx=5) 68 69 #### サンプル問題(初級) #### 70 sample_list = [ 71 0,0,0,8,0,1,9,5,0, 72 0,0,0,7,9,0,8,0,0, 73 0,0,3,5,2,0,7,0,4, 74 7,6,0,4,0,0,0,9,1, 75 3,4,0,9,0,8,5,2,0, 76 9,5,2,1,3,7,4,8,0, 77 0,7,0,0,0,4,0,0,8, 78 2,3,4,6,8,0,1,7,0, 79 1,0,0,0,0,9,0,0,0 80] 81 82 #### 配列を作り初期設定する #### 83 numpla_list =[] 84 85 for i in range(81): 86 numpla_list.append([0,1,2,3,4,5,6,7,8,9]) 87 88 #### マス目を作る #### 89 # 左クリックした際のイベント関数を定義。これは下でフレームにクリックイベントを定義しているけども、 90 # それよりも先に書かないとダメ 91 def left_click(event): 92 event.widget.configure(relief='sunken', bd=3) 93 except_num = event.widget.num 94 print(except_num) 95 96 97 i = 0 98 frame_list = [] 99 for x in range(9): 100 for y in range(9): 101 # タテヨコ40pxの小さいフレームを量産。reliefをraisedにして出っ張り感を再現する 102 frame = Frame(game_frame, width=40, height=40, bd=3, relief='raised', bg='LightGray') 103 # bindメソッドを使うと、そのオブジェクトにイベントを定義できる。 104 # 第一引数に<1>を指定すると左クリックした際のイベントとなる 105 # 第二引数には呼び出される関数(left_click関数)を記述する 106 frame.bind("<1>", left_click) 107 # frameにnumアトリビュートを定義する 108 frame.num = i 109 # 作成したフレームをフレームのリストに格納する。これでインデックス番号でアクセスすることで 110 # 各フレームを操作できる 111 frame_list.append(frame) 112 # gridを使ってフレームを配置する。packと違いgridを使うと、タテヨコ均等に9列x9列に配置できる 113 # rowでヨコ、columnでタテを指定している 114 frame.grid(row=x, column=y) 115 i += 1 116 117root.mainloop() 118 119

試したこと

Tkinterのリファレンスマニュアルやググったりして調べていますが、基本的知識が不足しすぎで解決策を見出せません。
かれこれ8時間くらい調べていますが、光明が見えません。

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

OS:Windows10
Python:Anaconda3
IDE:VS code

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

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

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

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

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

guest

回答2

0

変更箇所は主に3つ

  • gom() 内ではラベルに数値を設定して表示
  • label_list = [] ラベルを管理するリスト
  • Frame 生成と一緒に Label 生成

変更内容:

gom() 内で毎回新しいラベル生成しているのを、
初期化時一度のみに変更。

python

1from tkinter import * 2 3#### Call関数定義 #### 4def fim1(): 5 print("新規(N)") 6 7def fim2(): #暫定的にとりあえずサンプルを入れる 8 global numpla_list 9 for i in range(81): 10 numpla_list[i][0] = sample_list[i] 11 12def fim3(): 13 print("保存(S)") 14 15def gom(): 16 for i, label in enumerate(label_list): 17 label["text"] = numpla_list[i][0] 18 print(numpla_list[i][0]) 19 20 21def hem(): 22 print("ヘルプ") 23 24if __name__ == '__main__': 25 26 root = Tk() 27 28 menubar = Menu(root) 29 #### File menu #### 30 filemenu = Menu(menubar,tearoff=0) 31 filemenu.add_command(label='新規(N)', command = fim1) 32 filemenu.add_command(label='開く(O)', command = fim2) 33 filemenu.add_command(label='保存(S)', command = fim3) 34 filemenu.add_separator() 35 filemenu.add_command(label='終了(X)', command = quit) 36 37 #### Go Menu #### 38 gomenu = Menu(menubar,tearoff=0) 39 gomenu.add_command(label='実行(U)', command = gom) 40 41 #### Help Menu #### 42 helpmenu = Menu(menubar, tearoff=0) 43 helpmenu.add_command(label="ヘルプ(H)", command = hem) 44 45 #### メインメニュー #### 46 menubar.add_cascade(label="ファイル(F)", menu = filemenu) 47 menubar.add_cascade(label="実行(U)", menu = gomenu) 48 menubar.add_cascade(label="ヘルプ(H)", menu = helpmenu) 49 50 51 root.config(menu=menubar) 52 53 root.title("ナンバープレース") 54 root.minsize(300,300) 55 root.rowconfigure(0,weight=1) 56 root.columnconfigure(0,weight=1) 57 root.grid() 58 59 ###フレームオブジェクト作成### 60 root_frame = Frame(root, relief='groove', borderwidth=5, bg='LightGray') 61 status_frame = Frame(root_frame, height=50, relief='sunken', borderwidth=3, bg='LightGray') 62 game_frame = Frame(root_frame, relief='sunken', borderwidth=3, bg='LightGray') 63 root_frame.pack() 64 status_frame.pack(pady=5, padx=5, fill='x') 65 game_frame.pack(pady=5, padx=5) 66 67 #### サンプル問題(初級) #### 68 sample_list = [ 69 0,0,0,8,0,1,9,5,0, 70 0,0,0,7,9,0,8,0,0, 71 0,0,3,5,2,0,7,0,4, 72 7,6,0,4,0,0,0,9,1, 73 3,4,0,9,0,8,5,2,0, 74 9,5,2,1,3,7,4,8,0, 75 0,7,0,0,0,4,0,0,8, 76 2,3,4,6,8,0,1,7,0, 77 1,0,0,0,0,9,0,0,0 78] 79 80 #### 配列を作り初期設定する #### 81 numpla_list =[] 82 83 for i in range(81): 84 numpla_list.append([0,1,2,3,4,5,6,7,8,9]) 85 86 #### マス目を作る #### 87 # 左クリックした際のイベント関数を定義。これは下でフレームにクリックイベントを定義しているけども、 88 # それよりも先に書かないとダメ 89 def left_click(event): 90 event.widget.configure(relief='sunken', bd=3) 91 except_num = event.widget.num 92 print(except_num) 93 94 95 i = 0 96 frame_list = [] 97 label_list = [] 98 for x in range(9): 99 for y in range(9): 100 # タテヨコ40pxの小さいフレームを量産。reliefをraisedにして出っ張り感を再現する 101 frame = Frame(game_frame, width=40, height=40, bd=3, relief='raised', bg='LightGray') 102 # bindメソッドを使うと、そのオブジェクトにイベントを定義できる。 103 # 第一引数に<1>を指定すると左クリックした際のイベントとなる 104 # 第二引数には呼び出される関数(left_click関数)を記述する 105 frame.bind("<1>", left_click) 106 # frameにnumアトリビュートを定義する 107 frame.num = i 108 # 作成したフレームをフレームのリストに格納する。これでインデックス番号でアクセスすることで 109 # 各フレームを操作できる 110 frame_list.append(frame) 111 # gridを使ってフレームを配置する。packと違いgridを使うと、タテヨコ均等に9列x9列に配置できる 112 # rowでヨコ、columnでタテを指定している 113 frame.grid(row=x, column=y) 114 115 # ラベルを作成 116 frame.pack_propagate(False) 117 label = Label(frame, bg = 'LightGray') 118 label.pack(fill=BOTH, expand=1) 119 label_list.append(label) 120 121 i += 1 122 123root.mainloop()

投稿2020/05/03 08:31

teamikl

総合スコア8760

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

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

Rintaco

2020/05/03 17:29

質問の仕方が悪かったですね。 パズルゲームの画面表示なので、問題があって回答があるため、数字は少なくとも2回は表示する必要があります。(できれば、途中の計算過程も見たいので複数回になる可能性もあります) Labelではなくて、ButtonウィジェットのTEXTの方が良いのではないかと思い始めている今日この頃。
teamikl

2020/05/03 22:06 編集

複数回表示でも問題ありませんよ。 最初の問題点は、どのウィジェットに表示するかに関わらず、 (gom()関数内で) 「毎回新しいラベルを生成」している点でしたので、 計算過程では作成済みのウィジェットに表示することで解消できます。 ラベルの部分を他のウィジェットに変えるだけでは、 毎回生成するという問題自体は変わりません。
teamikl

2020/05/03 22:14

あ、誤解に気が付いたので、説明補足です。 最初の問題は「ラベルが表示されない」でしたので、質問の仕方自体は問題ありません。 ここで取り上げた「毎回新しいラベルを生成」の問題は、表示がうまくいった後の問題で、 元コードの意図通りでは関数gom()内でしたので、最初の回答ではそのままにしてましたが、 解消するには、このように、初期化時に一度のみ作成するようにします。 ラベルの代わりにボタンを使う場合も同様です。
guest

0

表示されない原因は2点

  • Label の親となっている game_frame が意図したものと違う。

Frame 上に作成するなら、frame_list[i] を Label の第一引数にします。

  • pack()/grid()/place() 等の配置関数が呼び出されていない。

表示されない直接的な原因。

また、Label 作成時にレイアウトが崩れてしまう為、
親ウィジェットのサイズを変更してしまわないように
pack_propagete(False) を呼び出しておきます。

python

1def gom(): 2 for i in range(81): 3 frame_list[i].pack_propagate(False) 4 label = Label(frame_list[i], text = numpla_list[i][0], bg = 'LightGray') 5 label.pack(fill=BOTH, expand=1)

※ 但し、2回目にこの関数を呼び出すと、Labelが2重に作成されるので、
そこから先は工夫してみてください。
Frame 上に予め空文字でLabelを作成しておいてから、gom() 関数では文字のみを設定する等。

イメージ説明

投稿2020/05/02 07:47

編集2020/05/02 07:59
teamikl

総合スコア8760

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

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

Rintaco

2020/05/03 08:01

回答ありがとうございました。 確かに文字がでてきましたが、「2回目にこの関数を呼び出すと、Labelが2重に作成される」という意味が、2回目読んでみてよくわかりました。 Labelを使って数値を表示しようとすること自体が間違いのような気がしてきたので、他のウィジェットつかったらどうなるか試してみます。
teamikl

2020/05/03 08:19

Labelへの表示自体は大丈夫ですが、 Label作成する場所は Frameと一緒に、 初期化時、最初に一度だけとするのが良いですね。 各セルのFrame を作成してるところで Label も作成して、 frame_list の代わりに label_list を作り、 gom() 内では label への値設定。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問