🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

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

Q&A

解決済

1回答

8339閲覧

Python:画像を更新したい

saberoa

総合スコア1

Python 3.x

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

0グッド

0クリップ

投稿2021/03/24 08:00

前提・実現したいこと

画像を2つ用意します、1つは名前をimgA.pngとしてプログラムを実行
ウィンドウ内に1つ目の画像が表示されます
実行中に1つ目の画像の名前を適当な物に変え、用意した2つ目の画像の名前をimgA.pngに変更します。
ウィンドウにある入力ボックスをエンターで決定後用意した2つ目に画像が変わるプログラム実現させたい

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

ウィンドウ内の画像が更新できない

該当のソースコード

Python

1import tkinter 2import cv2 3from PIL import Image, ImageTk 4 5def calc(event): # Etnerキー押下時の動作 6 textBox1.delete(0,tkinter.END) 7 #ここにプログラムがはいる? 8 9root = tkinter.Tk() 10root.geometry("800x550") # 画面サイズ 11image_1 = cv2.imread("imgA.png") 12image_2 = cv2.cvtColor(image_1, cv2.COLOR_BGR2RGB) # imreadはBGRなのでRGBに変換 13image_3 = Image.fromarray(image_2) # RGBからPILフォーマットへ変換 14image_4 = ImageTk.PhotoImage(image_3) # ImageTkフォーマットへ変換 15canvas = tkinter.Canvas(root, width=400, height=600,) # Canvas作成 16canvas.create_image(200, 300, image=image_4) # ImageTk 画像配置 17canvas.pack() 18textBox1 = tkinter.Entry(width=100) # 入力用テキストボックス 19textBox1.place(x=100, y=5) # テキストボックス位置指定 20textBox1.focus_set() # テキストボックスにフォーカス指定 21textBox1.bind('<Return>', calc) 22root.mainloop()

試したこと

リロードをする関数かなにかがあればできる?

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

質問主:python初心者 vbaは業務の簡易化にコードを書く程度
python 3.9.2 64-bit

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

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

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

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

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

guest

回答1

0

ベストアンサー

canvas.create_image の戻り値を控えておきます。

python

1imageItemID = canvas.create_image(200, 300, image=image_4) # ImageTk 画像配置

画像を変更したい場所で、canvas.itemconfigure を使い更新

python

1canvas.itemconfigure(imageItemID, image=image_X) # image_X は 新しいPhotoImage

もしくは、canvas.delete で一旦削除してから、新たに canvas.create_image。


注意点は、PhotoImage オブジェクトを管理する変数の生存期間。

image_4 はグローバル変数なので、ずっと残り続ける為問題ありませんが、
もし、差し替えたい画像を calc 関数内のローカル変数にした場合は、
関数を抜ける時点で PhotoImage が破棄されてしまう為、画像が表示されません(エラーにもなりません)

python

1import tkinter 2 3 4def calc(event): # Etnerキー押下時の動作 5 textBox1.delete(0,tkinter.END) 6 #ここにプログラムがはいる? 7 8 9 # NG: ここでローカル変数」に読み込む場合、画像は calc() が終わった後に破棄される。 10 # imageB = tkinter.PhotoImage(file="imgB.png") 11 12 canvas.itemconfigure(imageItem, image=imageB) 13 14 15root = tkinter.Tk() 16root.geometry("800x550") # 画面サイズ 17 18# ここで画像を準備。因みに古いバージョンでなければ png ファイルは対応してます。 19imageA = tkinter.PhotoImage(file="imgA.png") 20imageB = tkinter.PhotoImage(file="imgB.png") 21 22canvas = tkinter.Canvas(root, width=400, height=600,) # Canvas作成 23imageItem = canvas.create_image(200, 300, image=imageA) # ImageTk 画像配置 24canvas.pack() 25textBox1 = tkinter.Entry(width=100) # 入力用テキストボックス 26textBox1.place(x=100, y=5) # テキストボックス位置指定 27textBox1.focus_set() # テキストボックスにフォーカス指定 28textBox1.bind('<Return>', calc) 29root.mainloop() 30

投稿2021/03/24 08:46

teamikl

総合スコア8717

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

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

saberoa

2021/03/26 02:12

回答ありがとうございます! calcの中で image_1 = cv2.imread("imgB.png") とかやってもだめだったのは消えてたんですね、 Pythonのスコープについてもう少し理解を深めていきます!
teamikl

2021/03/26 03:32

> calcの中で image_1 = cv2.imread("imgB.png") > とかやってもだめだったのは消えてたんですね、 厳密には、ここではなく ImageTk.PhotoImage の部分ですね。 Tkinter では Widget (Label, Button 等) であれば、ライブラリ側で管理される為、 ローカル変数でも問題ありませんが、 非Widget (StringVar, PhotoImage 等) は、Tkinter の実装で デストラクタで破棄される設計になってる為、独自にオブジェクトの生存管理が必要です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問