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

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

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

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

Python

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

Q&A

解決済

1回答

888閲覧

基本的な処理が上手くいかない

takatoyo

総合スコア13

Tkinter

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

Python

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

0グッド

0クリップ

投稿2021/10/28 15:48

前提・実現したいこと

Python勉強中の初心者です。
麻雀初心者支援ツールを作りたいと思い、アプリケーションの作成を行っているのですがcanvasに画像が表示されない等様々な問題にぶつかって困っています。

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

直面している問題は

①辞書を作成し各要素にその画像を入れたいが入れ方がわからない(例えば一筒を呼び出したら一筒の牌の画像が値として返ってくる)
②試しにcanvas上に画像を表示させようとしたが、画像が表示されない
③「次へ」ボタンを押したら同じウィンドウ内で画面が切り替わるようにしたいが方法がわからないので仕方なく元のウィンドウを閉じて新しいウィンドウを作る手法を取っている。しかしなぜが元のウィンドウが閉じず、新しいウィンドウが開かない

の3つです。
初心者質問で恐縮ですがどうかよろしくお願いします。

該当のソースコード

Python

1import cv2 2from PIL import Image,ImageTk 3import tkinter as tk 4 5pai_man = {"man1":man1.png,"man2":2,"man3":3,"man4":4,"man5":5,"man6":6,"man7":7,"man8":8,"man9":9} 6pai_pin = {"pin1":1,"pin2":2,"pin3":3,"pin4":4,"pin5":5,"pin6":6,"pin7":7,"pin8":8,"pin9":9} 7pai_sou = {"sou1":1,"sou2":2,"sou3":3,"sou4":4,"sou5":5,"sou6":6,"sou7":7,"sou8":8,"sou9":9} 8pai_jihai = {"ji1":"東","ji2":"南","ji3":"西","ji4":"北","ji5":"白","ji6":"發","ji7":"中"} 9pai_images = {**pai_man,**pai_pin,**pai_sou,**pai_jihai} 10 11global img 12img = Image.open(pai_images[man1]) 13 14def btn1_click(): 15 root.destroy() 16 root_intro = tk.Tk() 17 root_intro.geometry('1200x700') 18 root_intro.title('ルールを知らない人向け(入門編)') 19 root_intro.label = tk.Label(root_intro,font=('MSゴシック','20','bold'), text='このステップは麻雀のルールを全く知らない人向けです\nまずは麻雀の基本から学んでいきましょう') 20 root_intro.label.place(x=250,y=200) 21 btn3 = tk.Button(root_intro, text='次へ',width=8, command=btn3_click) 22 btn3.pack(side=tk.RIGHT) 23 root_intro.mainloop() 24 25def btn2_click(): 26 root.destroy() 27 root_beginner = tk.Tk() 28 root_beginner.geometry('1200x700') 29 root_beginner.title('ルールを覚えた人向け(初級者編)') 30 root_beginner.mainloop() 31 32def btn3_click(): 33 root_intro.destroy() 34 root_pai_images = tk.Tk() 35 root_pai_images.geometry('1200x700') 36 root_pai_images.title('ルールを知らない人向け(入門編') 37 root_pai_images.label = tk.Label(root_pai_images,font=('MSゴシック','20','bold'), text='まず麻雀に使用する道具に「牌(ぱい、はい)」と呼ばれるものがあります\nこれは27種の数牌(すうはい、かずはい)と7種の字牌(じはい)から成り、\n1種類につき4個存在するので計34種136個の牌を用いてゲームを行います。') 38 root_pai_images.label.place(x=100,y=200) 39 canvas = tk.Canvas(root_pai_images,bg="green",width=1200, height=400) 40 canvas.place(x=0,y=350) 41 canvas.create_image(10,500,image=img) 42 root_pai_images.mainloop() 43 44root = tk.Tk() 45root.geometry('1200x700') #*ではなく小文字のxで記述 46root.title('麻雀初心者支援ツール') 47btn1 = tk.Button(root, width=80,height=10,font=('MSゴシック','15','bold'),text = 'ルールがわからない人向け',anchor=tk.CENTER,command=btn1_click) 48btn1.pack(fill = 'x', padx=100) 49btn2 = tk.Button(root, width=80,height=10,font=('MSゴシック','15','bold'),text='ルールを覚えた人向け',anchor=tk.CENTER,command=btn2_click) 50btn2.pack(fill='x', padx=100) 51 52root.mainloop()

試したこと

①辞書の"man1"の値に萬子の1の画像の名前などを入れてみましたが
'man1' is not defined
とエラーメッセージが表示されたのでおそらく入れられてないと思います。
②こちらも
canvas.create_image(10,500,image=img) 
の右辺の部分に画像の名前を入れてみましたがうまくいきませんでした。
global変数でimgを宣言してみましたがうまくいきませんでした。
③btn1で1度「ウィンドウを閉じて新しいウィンドウを開く」という処理を行う際はうまくいったのですが、btn3で同じコードで実行するとエラーが発生してしまいました。

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

表示したい画像はworkspaceの該当のソースコードと同じフォルダーに入っています。

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

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

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

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

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

guest

回答1

0

ベストアンサー

'man1' is not definedとエラーメッセージが表示された

man1.png は文字列型になってなく、変数man1のpng属性を参照しようとしてます。
正しくは、"man1.png" です。


btn3で同じコードで実行するとエラーが発生

root はグローバル変数なので、他関数内でも正常に参照できますが、
root_intro, root_beginner, root_pai_images はローカル変数なので、
他の関数からは参照出来ません。

対策: global 宣言をする

python

1 2def btn1_click(): 3 global root_intro 4 5 root.destroy() 6 root_intro = tk.Tk() 7

Tkinter では、tk.Tk() はウィンドウ表示のみではなく、
ライブラリの初期化もされる為、
tk.Tk() や mainloop を1つのプログラム内で複数回呼び出すのは、
意図しない挙動の原因になる事があり、好ましくありません。

複数のウィンドウが必要な場合は、tk.Toplevel を用います。

同じウィンドウ内で画面が切り替わるようにしたい

とのことなので、「画面遷移」について調べて見て下さい。

  • フレームに重ねて表示させて、tkraise というメソッドで

 一番上に表示するフレームを切り替える方法。

  • 表示中のウィジェットをdestroyで破棄して、新たに生成する方法。
  • ttk.Notebook を用いて、タブを非表示にする。

試しにcanvas上に画像を表示させようとしたが、画像が表示されない

変数 img は PIL.Image なので、PhotoImage にする必要があります。

注意点: PhotoImage を格納する変数は、ローカル変数ではいけません。
デストラクタが設定されてる為、関数を抜けると破棄されてしまいます。

また、画像読込に PIL を用いてますが、png は tk側で対応してます。
(古いバージョンでは png に対応しておらず、PILを使う必要がありました)

python

1 2# XXX: トップレベルでの global 宣言は不要。 3# Python では関数内でglobal 変数の代入がある場合に用います。 4# global img 5 6# XXX: PhotoImage が使えるのは tkinter の初期化 tk.Tk() 以降 7 8img = tk.PhotoImage(file="man1.png") 9 10# NOTE: img は何処かに格納しておく 11# 関数内の場合はグローバル宣言する等 12 13canvas.create_image(100, 100, image=img) 14

投稿2021/10/29 00:43

teamikl

総合スコア8664

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

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

takatoyo

2021/10/29 14:36

まさにやりたかったことです!ありがとうございます。 ②、③は解決しました! ①は辞書の値としてワークスペースに入っている画像を格納することは可能なのでしょうか? canvas.create_image(100,100,image="辞書内の欲しい画像が格納されているキー") といった形で画像を出力したいのですが
teamikl

2021/10/29 15:20

PhotoImage を生成する時の name に、そのキーを指定すれば可能です。 その前に、 canvas で表示させるには、事前に PhotoImage オブジェクトを生成する必要があります。 tk.TK() を複数回呼び出す場合は、その都度初期化されるので、毎回画像の読み直しが必要になるはずです。 まずは、tk.Tk()/mainloop をプログラム中で一度のみ使うようにしましょう。 準備を済ませれば create_image の image に指定するのは PhotoImageのID (文字列) でも良いので、 image に文字列を渡す事も可能です。 img = tk.PhotoImage(file="man1.png", name="man1") canvas.create_image(100, 100, image=img) # 通常は PhotoImage オブジェクトを渡しますが canvas.create_image(100, 100, image="man1") # nameで指定した文字列を渡す事も可能です
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問