51826


画像が変化しながら画像の表示座標を移動する、といった機能があるプログラムを作っているのですが、実行するとたまにラグっているように見えることがあります。

[code]

    import tkinter as tk
    class App(object):
        def GUI(self):
            root=tk.Tk()
            root.geometry("600x600")
    
            self.pic001=tk.PhotoImage(file="picture001.png")
            self.pic002=tk.PhotoImage(file="picture002.png")
    
            self.canvas = tk.Canvas(bg="black", width=796, height=816)
            self.canvas.place(x=0, y=0)
    
            self.item=self.canvas.create_image(0, 0, image=self.pic001, anchor=tk.NW)
    
            self.canvas.move(self.item,-51,10)
            self.canvas.itemconfig(self.item, image = self.pic002)    
    
            root.mainloop()
    app=App()
    app.GUI()
    
[/code]

基本的にはこれで実行しても問題はないのですが  
しかしこのコードをもっと正確に言えば、画像表示位置を変えた後に画像を差し替える  
という事になります。

そのため、処理が重くなる？と画像表示が思うようにいかず、ラグっているように見えるのだと思います。  
この問題を解決するには、画像差し替えと座標移動を同時に行う必要性があると思うのですが、どうすればそれを成すことができるでしょうか？

一応今のところ、プログラムはこんな感じにラグっています  
[![ラグ](https://i.stack.imgur.com/1Lxc6.gif)](https://i.stack.imgur.com/1Lxc6.gif)


CC BY-SA 4.0
2019-01-08T05:12:15.677
51816
2019-01-09T00:11:20.923
2019-01-08T20:08:33.340
31713
31713
question
python tkinter
Canvasの画像に対して、画像差し替えと場所移動を同時に行いたい


それは「モーフィング」と呼ばれる技術でしょう。  
あまりtkinterだけで出来るとは思えないのですが。  
むしろ動画作成・編集ソフトの範疇と考えられます。

「動画作成 モーフィング」で検索すると、こんなのが関連しそうです。  
PythonならOpenCVとかを使うようにすれば出来るのでは？  
[OpenCVで顔のモーフィングを実装する](https://blog.negativemind.com/2016/04/29/morphing-by-
opencv/)  
[Face Morph Using OpenCV — C++ / Python](https://www.learnopencv.com/face-
morph-using-opencv-cpp-python/)

単体のツールならこんなのがあります。  
[【AviUtl】モーフィング動画の作り方【アハ体験みたいに画像を徐々に変化させる】](http://aviutl.info/morphing/)  
[モーフラッシュ](http://starmediasoft.com/application/morphrush/),
[フェイスモーフ](http://starmediasoft.com/application/facemorph/)  
[複数画像からモーフィング動画が作成できるフリーソフト 『Sqirlz
Morph』](https://pc.mogeringo.com/archives/40557)

* * *

**更新を受けて**  
なるほど、アニメーションとかゲーム的な何かですね。  
だとすると、こちら辺りが参考になると思われます。  
[Python Tkinter refresh canvas](https://stackoverflow.com/q/21357178/9014308)  
[Tkinter canvas animation
flicker](https://stackoverflow.com/q/41308900/9014308)  
[Moving balls in Tkinter Canvas](https://stackoverflow.com/q/25430786/9014308)

たぶん肝となるのは Python Tkinter refresh canvas 回答のこの部分でしょう。  
google翻訳したものを載せます。

> キャンバスを更新する唯一の方法は、イベントループで「再描画」イベントを処理することです。
> あなたのループでは、イベントループに更新の機会を与えることは決してないので、変更はありません。
>
> 簡単な解決策はself.canvas.update_idletasksを呼び出すことですが、それは単なるハックであり、適切な解決策ではありません。
>
> アニメーションを実行する適切な方法は、イベントループを使用して反復を実行することです。
> これを行うには、作業をキュー（この場合はアイドルイベントキュー）に配置します。 afterコマンドでこのキューに物を置くことができます。
>
> あなたがすべきことはあなたのアニメーションの1回の反復を行う関数を書くことです。
> 基本的に、whileループ内のすべてのものを受け取り、それを関数に移動します。
> それから、やるべき仕事がある限り、その関数が継続的に呼び出されるように手配します。
> その関数の中にafterを呼び出すことも、アニメーションを制御する別の関数を持つこともできます。

それから、こちらは pygame を使った場合のQ&Aですが、考え方は同等でしょう。  
[Flickering dice image when i press my dice
button.](https://www.reddit.com/r/pygame/comments/42rcbf/flickering_dice_image_when_i_press_my_dice_button/)

ご質問のソースがどれだけ実際と合っているか不明ですが、上記を元に考えると、スクリーンやキャンバスの設定・初期化およびメインループ等は別のクラスや関数に移動する。1つのフレームを更新する処理を1つにまとめて、それを定期的に呼び出す。といったあたりでしょうか。

試してみてください。


CC BY-SA 4.0
2019-01-08T16:56:48.707
51826
2019-01-09T00:11:20.923
2020-06-17T08:14:45.997
-1
26370
51816
answer