Python Tkinter进入事件

时间:2015-09-11 15:43:04

标签: python tkinter

我是Tkinter的新人,我试图制作一个动画按钮。

我使用了进入 - 离开事件,但点击按钮却没有很好地响应。

我的代码是:

    imagePath = "Resources/"
    imagelist = ["boton_1.gif","boton_2.gif","boton_3.gif","boton_4.gif","boton_5.gif","boton_6.gif",
                    "boton_7.gif","boton_8.gif","boton_9.gif","boton_10.gif","boton_11.gif","boton_12.gif",
                    "boton_13.gif","boton_14.gif","boton_15.gif","boton_16.gif"]


    giflist = []
    for imagefile in imagelist:
        photo = PhotoImage(file=imagePath+imagefile)
        giflist.append(photo)

    self.photo=giflist[0]
    button = Button(buttonFrame, image=self.photo,background='orange',activebackground='lightsalmon',
                    command=lambda: controller.show_frame(ListPlayerPage))
    button.pack(pady=5)

    def enter(event):
        self.clickOnButton1 = True
        for i in range(1,8):
            button.config(image=giflist[i])
            button.update()
            time.sleep(0.1)
            if self.clickOnButton1 == False:
                break
        while (self.clickOnButton1):
            for i in range (9,15):
                button.config(image=giflist[i])
                button.update()
                time.sleep(0.08)
                if self.clickOnButton1 == False:
                    break

    def leave(event):
        self.clickOnButton1 = False
        button.config(image=self.photo)
        button.update()

    button.bind("<Enter>",enter)
    button.bind("<Leave>",leave)

谢谢!

2 个答案:

答案 0 :(得分:1)

部分问题肯定与您调用sleep的事实有关。作为一个好的经验法则,你永远不应该在GUI的主线程中调用sleep。它阻止GUI处理所有事件,包括屏幕刷新。

一般来说,你也应该避免打电话给update。如果在处理update期间您最终调用再次调用update的方法,则可能会导致嵌套事件循环。

这是一个非常简单的解决方案示例,它创建了一个可以设置动画的按钮。它使用after迭代一个文本字符串列表,每半秒一个新字符串。此示例将永久制作动画,但您可以轻松地仅显示每个项目一次。这会修改文本以缩短示例,但您可以轻松修改它以更改图像而不是文本。

import Tkinter as tk # use tkinter for python 3.x
class AnimatedButton(tk.Button):
    def __init__(self, *args, **kwargs):
        tk.Button.__init__(self, *args, **kwargs)
        self._job = None

    def cancel_animation(self):
        if self._job is not None:
            self.after_cancel(self._job)
            self._job = None

    def animate(self, textlist):
        text = textlist.pop(0)
        textlist.append(text)
        self.configure(text=text)
        self._job = self.after(500, self.animate, textlist)

您可以像使用任何其他按钮一样使用它,但是您可以调用animate来启动动画,并cancel_animate取消它:

button = AnimatedButton(root, width=10)
data = ["one","two","three","four","five","six"]
button.bind("<Enter>", lambda event: button.animate(data))
button.bind("<Leave>", lambda event: button.cancel_animation())

答案 1 :(得分:0)

我按照Bryan Oakley的例子找到了一个很好的解决方案!

首先,这是一个带有复杂动画的动画按钮。我有16张图片。第一个是基本图像。然后我有八个图像,这是动画的第一部分。其余图像是动画的循环部分。

当您将鼠标放在按钮上时,动画开始。

这是代码!:

import Tkinter as tk # use tkinter for python 3.x

root = tk.Tk()
root.geometry("300x200")

class AnimatedButton(tk.Button):

    def __init__(self, *args, **kwargs):
        tk.Button.__init__(self, *args, **kwargs)
        self._job = None
        self.i = 1

    def cancel_animation(self,image):
        self.configure(image=image)
        self.i = 1
        if self._job is not None:
            self.after_cancel(self._job)
            self._job = None


    def animate(self, imagelist):
        image = imagelist[self.i]
        self.i+=1
        if self.i == (len(imagelist)-1):
            self.i = 9
        self.configure(image=image)
        self._job = self.after(80, self.animate, imagelist)


imagePath = "Resources/"
imagelist = ["boton_1.gif","boton_2.gif","boton_3.gif","boton_4.gif","boton_5.gif","boton_6.gif",
                "boton_7.gif","boton_8.gif","boton_9.gif","boton_10.gif","boton_11.gif","boton_12.gif",
                "boton_13.gif","boton_14.gif","boton_15.gif","boton_16.gif"]

giflist = []
for imagefile in imagelist:
    photo = tk.PhotoImage(file=imagePath+imagefile)
    giflist.append(photo)

image = giflist[0]
button = AnimatedButton(root,image = image)
button.bind("<Enter>", lambda event: button.animate(giflist))
button.bind("<Leave>", lambda event: button.cancel_animation(image))

button.pack()

root.mainloop()

感谢的!!!