2017-12-16 11 views
2

をスピードアップ私が仕事をしやすいTkinterではアニメーションGIFを表示するためのクラスを作ることにしましたが、動的にほとんどすべてのフレームを収集するプロセスは、常に時間の顕著な塊を取り、起こってから何かを防ぎますそれが終わるまで。私はそれをスピードアップする方法があるのか​​、同じことをするより効率的な方法があるのだろうと思っていました。ここでは、潜在的に長いタスク

は、クラスのコードです:

from tkinter import * 

class animation: 
    def __init__(self,*args,**kwargs): 
     self.root=args[0] 
     self.label=Label(self.root) 
     self.label.grid() 
     self.image=kwargs["image"] 
     try: 
      self.delay=kwargs["delay"] 
     except KeyError: 
      self.delay=20 

     self.frames=[] 
     x=0 
     while True: 
      try: 
       img=PhotoImage(file=self.image, 
           format="gif -index {}".format(x)) 
       self.frames.append(img) 
       x+=1 
      except: 
       break 


    def animate(self,y): 
     try: 
      self.label.configure(image=self.frames[y]) 
      self.root.after(self.delay,lambda:self.animate(y+1)) 
     except IndexError: 
      self.label.configure(image=self.frames[0]) 
      self.root.after(self.delay,lambda:self.animate(1)) 

、ここではそれが使用される方法です:

from tkinter import * 
from modules.animation import animation 

root=Tk() 

cosmog=animation(root,image="cosmog.gif").animate(0) 
cosmoem=animation(root,image="cosmoem.gif").animate(0) 
lunala=animation(root,image="lunala.gif").animate(0) 

root.mainloop() 
+0

多分、tkinterを始める前にすべてのイメージを読むクラスを作成してください。あるいは、スレッドを使ってファイルを読むこともできます。 – furas

+0

これはあまり役に立ちませんが、イメージを一度ロードしてから、フレームごとにHDDからイメージをロードするのではなく、すべてのフレームを引き出す必要があります。 [これはどうしたのですか](https://stackoverflow.com/a/43770948/2229945)。また、現在のウィジェットをサブクラス化することによって、tkinterウィジェットを作成する適切な方法に注目してください。そうすれば、コード内の他のウィジェット(パック、グリッド、tkraiseなど)と同じように扱うことができます。代わりに、 'self.root.after(self.delay、ラムダ:self.animate(1))の – Novel

+0

FWIW、' 'あなたはself.root.after使用することができます(self.delay、self.animateを、1)' –

答えて

0

はスレッドで、このようにしてみてください。

import threading 
import time 

def __init__(self, *args, **kwargs): 
    self.frames=[] 
    self.run_loop = True 
    self.x=0 
    self.taken = [] 
    self.order = [] 

    while self.run_loop: 
     threading.Thread(target=self.add_image).start() 

def add_image(self): 
    try: 
     if self.x not in self.taken: # make sure not several threads add the same image index 
      self.taken.append(self.x) 
      self.x+=1 
     else: 
      return 

     # save local x before creating image, for the order 
     # all the other threads will increment self.x while Image is created 
     x = self.x 

     img=PhotoImage(file=self.image, format="gif -index {}".format(self.x)) 

     self.frames.append(img) 
     self.order.append(x) # keep track of the order 

     if len(self.frames) == len(self.taken): # when finish 
      self.frames = [x for _,x in sorted(zip(self.order,self.frames))] # sort the frames to the order 

    except: 
     self.run_loop = False 

私が作りました単純な実行可能な例で、tkinterを使用せずに、time.sleep(ランダムな時間)を使用して、PhotoImageをシミュレートします。

import threading 
import time 
from random import randint 

class Test: 

    frames=[] 
    run_loop = True 
    x=0 
    taken = [] 
    order = [] 
    time = 0 

    def __init__(self): 
     while self.run_loop: 
      threading.Thread(target=self.add_image).start() 

    def add_image(self): 
     if self.x < 100: 
      if self.x not in self.taken: # make sure not several threads add the same image index 
       self.taken.append(self.x) 
       self.x+=1 
      else: 
       return 

      x = self.x 
      t = randint(1,10)/10.0 
      self.time += t 

      time.sleep(t) # PhotoImage random time.sleep 0 to 1 second 

      self.order.append(x) 
      self.frames.append(x) 

      if len(self.frames) == len(self.taken): 
       print("Frames before sort") 
       print(self.frames) 

       self.frames = [x for _,x in sorted(zip(self.order,self.frames))] 

       print("\nFrames after sort") 
       print(self.frames) 

       print("\nTime used combined: {} seconds".format(self.time)) 


     else: 
      self.run_loop = False 


t = Test() 

このテストでは、使用された合計時間は約50秒です。
100スレッドで、1秒で実行します。最も長い時間の量です。スリープ、0〜1秒です。
あなたのために、それ以上の長さを取るべきではありませんPhotoImage

関連する問題