2012-04-21 55 views
1

我做了一个非常简单的GUI,它有一个按钮并显示图像(.gif)。我的目标是每当你按下按钮时输出另一个.gif文件。在我的文件目录中有2个.gif文件,并且每当你按下按钮时都要在这两个文件之间切换。当按下按钮时显示重复图像的简单GUI

#Using python2.7.2 
import Tkinter 

root = Tkinter.Tk() 

try: 
    n 
except: 
    n = 0 

def showphoto(par): 
    if par%2 == 0: 
     try: 
      label2.destroy() 
     except: 
      pass 
     photo = Tkinter.PhotoImage(file="masc.gif") 
     label2 = Tkinter.Label(image=photo) 
     label2.image = photo 
     label2.pack() 

    else: 
     try: 
      label2.destroy() 
     except: 
      pass 
     photo = Tkinter.PhotoImage(file="123.gif") 
     label2 = Tkinter.Label(image=photo) 
     label2.image = photo 
     label2.pack() 

myContainer1 = Tkinter.Frame(root, width = 100, height = 100) 
myContainer1.pack() 

def callback(event): 
    global n 
    showphoto(n) 
    n = n + 1 

button1 = Tkinter.Button(myContainer1) 
button1["text"]= "Next pic" 
button1["background"] = "green" 
button1.bind("<Button-1>", callback(n))  
button1.pack()     

root.mainloop() 

当前的代码只是输出第一图像(masc.gif),但是当我按下按钮不切换到另一图像(123.gif)。我究竟做错了什么?

+0

我觉得这个代码,你只需要使用n回调的全球外。而不是'try:n;除了:n = 0',为什么不使用'global n; n = 0'? – gary 2012-04-21 17:03:59

+0

我这样做,它不会改变任何东西。另外,据我所知,在函数之外声明一个可变的全局是多余的。 – Bentley4 2012-04-22 08:43:44

回答

3

使用类可以更容易实现,因为该类可以在不使用全局变量的情况下保存所有必需的数据。

import Tkinter as tk 
from collections import OrderedDict 

class app(tk.Frame): 
    def __init__(self,master=None, **kwargs): 
     self.gifdict=OrderedDict() 
     for gif in ('masc.gif','123.gif'): 
      self.gifdict[gif]=tk.PhotoImage(file=gif) 
     tk.Frame.__init__(self,master,**kwargs) 
     self.label=tk.Label(self) 
     self.label.pack() 
     self.button=tk.Button(self,text="switch",command=self.switch) 
     self.button.pack() 
     self.switch() 

    def switch(self): 
     #Get first image in dict and add it to the end 
     img,photo=self.gifdict.popitem(last=False) 
     self.gifdict[img]=photo 
     #display the image we popped off the start of the dict. 
     self.label.config(image=photo) 

if __name__ == "__main__": 
    A=tk.Tk() 
    B=app(master=A,width=100,height=100) 
    B.pack() 
    A.mainloop() 

当然,这可能是更普遍的做...(图像周期通过例如可以通过列表),而这将通过所有的图像self.gifs切换...

这种方法也消除了每次销毁和重新创建标签的必要性,而不是我们重复使用我们已有的标签。

编辑

现在我用的OrderedDict来存储文件。 (密钥=文件名,值= PhotoImages)。然后我们弹出字典中的第一个元素进行绘图。当然,如果您使用的是python2.6或更早的版本,除了字典之外,您还可以保留一个列表并使用列表来获取密钥。

+0

这个版本泄漏内存 - 每次你切换你创建另一个图像。相反,创建图像并将其存储在字典中。下次切换时,请检查字典并使用已创建的图像(如果存在)。您也可以通过简单地从列表的前面拉取图像并将其添加到最后来消除混淆的索引计算。 – 2012-04-21 19:57:08

+0

@BryanOakley--它确实泄漏了内存吗?虽然确实每次切换都会创建一个新的图像,但旧的应该已经被垃圾收集了(我认为......)无论如何,改变列表的顺序是一个好主意(因为是字典),所以我编辑。唯一的缺点是你需要有足够的内存来存储整个gif序列。 – mgilson 2012-04-21 22:18:06

1
button1 = Tkinter.Button(myContainer1) 
button1["text"]= "Next pic" 
button1["background"] = "green" 
button1.bind("<Button-1>", callback(n)) 

首先,你绑定<Button-1>事件None(这就是callback(n)计算结果为)。您应该将其绑定到callback(不包括括号(也称呼叫运营商))。

其次,我建议你换callback不接受任何参数,取出bind呼叫,创建您的按钮:

button1 = Tkinter.Button(myContainer1, command=callback)