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

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

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

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

Pythonista

Pythonistaは、iOS上でPythonプログラミングができる開発アプリです。さらに、Pythonの関数・変数などを自動で補完する便利なコードエディタや、PythonスクリプトをiOS上で多様な形で機能させる各種機能も内包しています。

Tkinter

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

解決済

afterメソッドで、正確に「任意秒ごと」に動作させたい。

ppap
ppap

総合スコア66

Anaconda

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

Pythonista

Pythonistaは、iOS上でPythonプログラミングができる開発アプリです。さらに、Pythonの関数・変数などを自動で補完する便利なコードエディタや、PythonスクリプトをiOS上で多様な形で機能させる各種機能も内包しています。

Tkinter

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

1回答

0リアクション

1クリップ

593閲覧

投稿2022/09/01 14:47

編集2022/09/07 06:11

前提

pythonのtkinterでクリックにより画像を回転させ、再度クリックすることで回転が止まるアニメーションを作成しています。

afterメソッドで無限に画像を回転させる処理を行ったうえで、後から回転をストップさせるイベントを呼び出し、アニメーションの操作を実現しています。

画像を角速度5[deg/s]で回転させようとしているにも関わらず、想定より回転速度が遅いことに困っています。
おそらく、処理が重いことが大きな要因の一つだと思われます。

実現したいこと

画像を角速度5[deg/s]で回転させたいです。

しかし、現在備わっている
・左クリックで左回転スタート
・右クリックで右回転スタート
・左右いづれかのクリックで回転をストップ
という機能は必要です。

このような機能を保ちつつ、処理を軽くして角速度を命令通りに実行できるコードにするには、どのような改良をすると良いでしょうか?

該当のソースコード

python

import tkinter as tk from PIL import Image, ImageTk import datetime #新規ウィンドウを作成 root = tk.Tk() root.attributes("-fullscreen", True) #画面サイズの指定 WIDTH = root.winfo_screenwidth() HEIGHT = root.winfo_screenheight() #ウィンドウ上にフレームを作成 frame = tk.Frame(root) frame.place(x = -5, y = -5, width = WIDTH + 10, height = HEIGHT + 10) #フレーム上に、キャンバスを作成 canvas = tk.Canvas(frame, width = WIDTH, height = HEIGHT, bg = "black") canvas.place(x = 0, y = 0, width = WIDTH + 10, height = HEIGHT + 10) #画像のプリセット角を"cs"として定義 cs = 0 #キャンバスにSVV画像を貼り付け img = Image.open("D:\EXPERIMENT\programming\Python\SVV\svv_bar.png") img = img.rotate(cs) tkimg = ImageTk.PhotoImage(img, width = WIDTH, height = HEIGHT) canvas.create_image(WIDTH/2, HEIGHT/2, image=tkimg, anchor="center", tags="img") #キャンバスに、透明な画像を貼り付け img_snow = Image.open("D:\EXPERIMENT\programming\Python\SVV\svv_snow.png") tkimg_snow = ImageTk.PhotoImage(img_snow, width = WIDTH, height = HEIGHT) canvas.create_image(WIDTH/2, HEIGHT/2, image=tkimg_snow, anchor="center", tags="img_snow") #"c"の初期値を定義 c = 0 #角速度の指定 interval = datetime.timedelta(milliseconds = 20) #左回転時の基準時刻を取得し、press_Lに渡す def press_L(event): global next_time_L next_time_L = datetime.datetime.now() rotate_L(event) #右回転時の基準時刻を取得し、press_Rに渡す def press_R(event): global next_time_R next_time_R = datetime.datetime.now() rotate_R(event) def rotate_L(event): global interval global next_time_L global img global tkimg global c c = c + 1 R = c / 10 canvas.delete("all") IMG = img.rotate(R, resample = Image.BICUBIC) tkimg = ImageTk.PhotoImage(IMG) canvas.create_image(WIDTH/2, HEIGHT/2, image = tkimg, anchor = "center", tags = "img") canvas.create_image(WIDTH/2, HEIGHT/2, image=tkimg_snow, anchor = "center", tags="img_snow") next_time_L += interval now = datetime.datetime.now() delay_ms = int((next_time_L - now).total_seconds() * 1000) id = root.after(delay_ms, rotate_L, None) def stop_L(event): root.after_cancel(id) canvas.tag_bind("img_snow", "<ButtonPress-1>", press_L) canvas.bind("<ButtonRelease-1>", stop_L) def rotate_R(event): global interval global next_time_R global img global tkimg global c c = c - 1 R = c / 10 canvas.delete("all") IMG = img.rotate(R, resample = Image.BICUBIC) tkimg = ImageTk.PhotoImage(IMG) canvas.create_image(WIDTH/2, HEIGHT/2, image = tkimg, anchor = "center", tags = "img") canvas.create_image(WIDTH/2, HEIGHT/2, image=tkimg_snow, anchor = "center", tags="img_snow") next_time_R += interval now = datetime.datetime.now() delay_ms = int((next_time_R - now).total_seconds() * 1000) id = root.after(delay_ms, rotate_R, None) def stop_R(event): root.after_cancel(id) canvas.tag_bind("img_snow", "<ButtonPress-3>", press_R) canvas.bind("<ButtonRelease-3>", stop_R) def finish(event): #Enterキーを押すことで全画面表示を終了し、回転角度を取得する root.destroy() print(-c / 10) #左クリックで呼び出すイベント canvas.tag_bind("img_snow", "<ButtonPress-1>", press_L) #右クリックで呼び出すイベント canvas.tag_bind("img_snow", "<ButtonPress-3>", press_R) #Enterキーで呼び出すイベント root.bind("<Return>", finish) #メインループ root.mainloop() #end.

上記の処理に使用した画像を作成するコード

python

from PIL import Image, ImageDraw #背景色が黒色のキャンパスを作成。 im = Image.new('RGB', (500, 500), (0, 0, 0)) draw = ImageDraw.Draw(im) #中央に線を描画 draw.line((50, 250, 450, 250), fill=(255, 255, 255), width=10) #同じサイズの画像を作成 im_clear = Image.new("RGBA", im.size, (0, 0, 0, 0)) width = im.size[0] height = im.size[1] #色ごとに処理 for x in range(width): for y in range(height): pixel = im.getpixel( (x, y) ) # 黒なら処理しない if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0: continue # 黒以外なら、用意した画像にピクセルを書き込み im_clear.putpixel( (x, y), pixel ) #SVVで表示させるバーをpng形式で保存 im_clear.save("D:\EXPERIMENT\programming\Python\SVV\svv_bar.png", quality=100) #---透明なpng画像の作成--- #画像サイズの指定 WIDTH = 1600 HEIGHT = 1000 #新しい画像を作成 im_snow = Image.new("RGBA", (WIDTH, HEIGHT), (0, 0, 0, 0)) #新しい画像をもう一つ作成 im_snow2 = Image.new("RGBA", (WIDTH, HEIGHT), (0, 0, 0, 0)) #色ごとに処理 for x in range(width): for y in range(height): pixel = im_snow2.getpixel( (x, y) ) # 黒なら処理しない if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0: continue # 黒以外なら、用意した画像にピクセルを書き込み im_snow.putpixel( (x, y), pixel ) #透明な画像をpng形式で保存 im_snow.save("D:\EXPERIMENT\programming\Python\SVV\svv_snow.png", quality=100)

試したこと

afterメソッドの指定時間を増やして、それに伴い "c + 0.005" の部分の数値を大きくするように変更しましたが、アニメーションがカクカク動いているように見えてしまうレベルまで処理の時間間隔を空けても、画像が360°回転するのに72秒以上の時間がかかってしまいました。
そのため、コードの改良が必要だと感じています。

呼び出すイベント関数が多いことが原因かと考え、関数の数を減らそうと試みましたが、現時点の数までしか減らせませんでした。
もし、さらに処理が軽くなるコードを思いつく方がいらっしゃいましたら、お力を貸して頂きたいです。

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

AnacondaでPythonを使用しています。
・Anacondaのバージョン:conda 4.12.0
・Pythonのバージョン:Python 3.9.12
・Windowsのバージョン:version 21H2

デバイスの仕様
・プロセッサ:11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz
・実装RAM:16.0 GB

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

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

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

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Anaconda

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

Pythonista

Pythonistaは、iOS上でPythonプログラミングができる開発アプリです。さらに、Pythonの関数・変数などを自動で補完する便利なコードエディタや、PythonスクリプトをiOS上で多様な形で機能させる各種機能も内包しています。

Tkinter

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