2014-12-04 33 views
1

我是一个大气科学家,为了创建一个简单的图像查看器,通过python(2.7使用PIL和Tkinter)挣扎着,它将显示我们最终生成的一些预测产品。我想实现一个开始,停止,前进,后退和循环按钮。循环按钮及其关联的回调当前正常工作。循环方法记入Glenn Pepper(通过谷歌发现一个开源项目)。 下面是代码:Tkinter图像查看器方法

from Tkinter import * 
from PIL import Image, ImageTk 
import tkMessageBox 
import tkFileDialog 

#............................Button Callbacks.............................# 

root = Tk() 
root.title("WxViewer") 
root.geometry("1500x820+0+0") 

def loop(): 
    StaticFrame = [] 
    for i in range(0,2): 

     fileName="filename"+str(i)+".gif" 
     StaticFrame+=[PhotoImage(file=fileName)] 
    def animation(currentframe): 

     def change_image(): 
      displayFrame.create_image(0,0,anchor=NW, 
         image=StaticFrame[currentframe], tag='Animate') 
      # Delete the current picture if one exist 
     displayFrame.delete('Animate') 
     try: 
      change_image() 
     except IndexError: 
        # When you get to the end of the list of images - 
        #it simply resets itself back to zero and then we start again 
      currentframe = 0 
      change_image() 
     displayFrame.update_idletasks() #Force redraw 
     currentframe = currentframe + 1 
      # Call loop again to keep the animation running in a continuous loop 
     root.after(1000, animation, currentframe) 
    # Start the animation loop just after the Tkinter loop begins 
    root.after(10, animation, 0) 


def back(): 
    print("click!") 

def stop(): 
    print("click!") 

def play(): 
    print("click!") 

def forward(): 
    print("click!") 
#..........................ToolFrame Creation............................# 

toolFrame = Frame(root) 
toolFrame.config(bg="gray40") 
toolFrame.grid(column=0,row=0, sticky=(N,W,E,S)) 
toolFrame.columnconfigure(0, weight = 1) 
toolFrame.rowconfigure(0, weight = 1) 
toolFrame.pack(pady = 0, padx = 10) 


backButton = Button(toolFrame, text="Back", command = back) 
backButton.pack(side = LEFT) 

stopButton = Button(toolFrame, text = "Stop", command = stop) 
stopButton.pack(side = LEFT) 

playButton = Button(toolFrame, text = "Play", command = play) 
playButton.pack(side = LEFT) 

forwardButton = Button(toolFrame, text = "Forward", command = forward) 
forwardButton.pack(side = LEFT) 

loopButton = Button(toolFrame, text = "Loop", command = loop) 
loopButton.pack(side = LEFT) 

toolFrame.pack(side = TOP, fill=X) 

#........................DisplayFrame Creation..........................# 
displayFrame = Canvas(root, width=1024,height=768) 
displayFrame.config(bg="white") 
displayFrame.grid(column=0,row=0, sticky=(N,W,E,S)) 
displayFrame.columnconfigure(0, weight = 1) 
displayFrame.rowconfigure(0, weight = 1) 
displayFrame.pack(pady = 5, padx = 10) 
displayFrame.pack(side = LEFT, fill=BOTH) 

#...............................Execution...............................# 

root.mainloop() 

这是相当简单的。我已经搜索了GitHub的项目,谷歌和stackoverflow,但我不确定如何使这五种方法相互发挥很好。任何人都可以分享一些关于如何构建其他四种方法的指示,以便它们适当地工作?感谢您的时间!

+0

Tkinter不知道是线程安全的,所以像这样的事情可能并不总是像它第一次出现那样直截了当。我会尝试使用线程安全的mtTkinter(http:// http://tkinter.unpythonic.net/wiki/mtTkinter),然后使用线程模块处理更新。 – 2014-12-04 18:34:27

回答

2

我会用下面的东西(未经测试)替换当前的循环函数。更改:添加一些全局名称以在函数之间共享数据;在current_image有效的情况下,使change_image完成更改图像所需的一切;除了起始值以外,当current_image改变时,它总是一个有效的图像号;因子forward()out of animate()(这只是重复次数前向调用)。

n_images = 2 
images = [PhotoImage(file="filename"+str(i)+".gif") for i in range(n_images)] 
current_image = -1 
def change_image(): 
    displayFrame.delete('Animate') 
    displayFrame.create_image(0,0, anchor=NW, 
         image=StaticFrame[current_image], tag='Animate') 
    displayFrame.update_idletasks() #Force redraw 

callback = None 
def animate(): 
    global callback 
    forward() 
    callback = root.after(1000, animate) 

这里有三个其他功能。

def forward(): 
    global current_image 
    current_image += 1 
    if current_image >= n_images: 
     current_image = 0 
    change_image() 

def back(): 
    global current_image 
    current_image -= 1 
    if current_image < 0: 
     current_image = n_images-1 
    change_image() 

def stop(): 
    if callback is not None: 
     root.after_cancel(callback) 
+1

所有这一切都很好!唯一的例外是stop方法,它抛出了错误TclError:wrong#args:应该是“在取消id |命令之后”这里的任何提示? – 3722839 2014-12-05 06:36:04

+2

我看到你为current_image添加了全局语句。我添加了一个用于回调的动画,并且一个警卫在回调为无时(清除错误)不会调用after_cancel。该文档说一个参数 - 一个从root.after(或after_idle)返回的id。我尝试了一个最简单的例子,这个工程。其他更改(如果不在您的版本中),代码是否会更好地工作? – 2014-12-05 22:54:46