鱼C论坛

 找回密码
 立即注册
查看: 4496|回复: 21

[已解决]python 2.7 tkinter 相关问题求救

[复制链接]
回帖奖励 2 鱼币 回复本帖可获得 2 鱼币奖励! 每人限 1 次
发表于 2017-6-4 14:41:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在刚大作业,遇到了几个问题,求救!!!!

第一个是,我想在tkinter主事件循环中做一个循环的动画,像这样
class .....:

def blink(self,win):
        if self.blinkFlag:
            #这里是各种操作
            self.win.update()
            sleep(0.005)
            self.blink(win)

def normal(self,win):
        if self.blinkFlag==False:
            self.blinkFlag=True
            self.blink(win)
        elif self.blinkFlag==True:
            self.blinkFlag=False

其中normal是绑定在一个按钮上的类内函数,作用是改变self.blinkFlag的值,这样可以起到控制动画的效果
但是这块东西有两个问题:
第一个是,sleep()函数是用来起到动画效果的,但是如果前面不加win.update()就会卡死,不知道是什么道理
第二个是,这个循环有很大的问题,我试过两种模式,一种是像上面这样的,blink写成递归函数,每次递归判断flag,被终止了就退出。另外一种是用while循环,写成:

def blink(self,win):
        while self.blinkFlag:
            #这里是各种操作
            self.win.update()
            sleep(0.005)

据说用while循环会有冲突,事实上这两种方法在循环次数不多的时候都没问题,次数一多就会溢出。而且如果在循环的过程中强行关闭窗口,就会报一大堆错误,类型是TclError
我觉得这里的解决方法可能需要用到 canvas控件的方法 .after 但是不太会用,求各位大神指导!!!!!!


最佳答案
2025-2-2 20:59:48
本帖最后由 惊晓欲仙 于 2025-2-2 21:07 编辑

首先进行问题分析
1. sleep 函数不加 win.update() 会卡死
在 Tkinter 中,主事件循环负责处理各种用户交互和界面更新。当你使用 time.sleep() 时,程序会暂停执行,这会阻塞主事件循环。也就是说,在 sleep 期间,Tkinter 无法处理新的事件(如鼠标点击、窗口重绘等),导致界面看起来像是卡死了。而 win.update() 会手动更新 Tkinter 的事件循环,使得在 sleep 之前界面有机会处理待处理的事件,避免卡死。
2. 递归和 while 循环的问题
递归:递归调用 blink 函数会不断增加调用栈的深度。当循环次数增多时,会导致栈溢出错误,因为 Python 对递归深度有一定的限制。
while 循环:while 循环同样会阻塞主事件循环,使得 Tkinter 无法正常处理其他事件。当你强行关闭窗口时,由于主事件循环被阻塞,Tkinter 无法正确处理窗口关闭事件,从而抛出 TclError 异常。
下面是解决方法(我用after来解决,使用 after 方法可以避免阻塞主事件循环,从而解决界面卡死和异常抛出的问题。同时,由于不会无限递归或使用 while 循环,也不会出现栈溢出的问题。但可以等会小甲鱼哦,甲鱼有可能有其他方法)
import tkinter as tk
import time

class BlinkAnimation:
    def __init__(self, win):
        self.win = win
        self.blinkFlag = False
        # 创建一个按钮
        self.button = tk.Button(win, text="Toggle Blink", command=lambda: self.normal(win))
        self.button.pack()

    def blink(self):
        if self.blinkFlag:
            # 这里是各种操作,例如更新标签文本
            # 示例:假设这里有一个标签
            label = tk.Label(self.win, text="Blinking...")
            label.pack()
            # 使用 after 方法在 5 毫秒后再次调用 blink 函数
            self.win.after(5, self.blink)

    def normal(self, win):
        if self.blinkFlag == False:
            self.blinkFlag = True
            self.blink()
        elif self.blinkFlag == True:
            self.blinkFlag = False

if __name__ == "__main__":
    root = tk.Tk()
    app = BlinkAnimation(root)
    root.mainloop()

有用点点支持,多多评分哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-9-30 15:08:22 | 显示全部楼层

回帖奖励 +2 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-10-1 11:42:57 | 显示全部楼层

回帖奖励 +2 鱼币

不会问版主吧!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-1 21:03:51 | 显示全部楼层

回帖奖励 +2 鱼币

本帖最后由 waitforlove 于 2018-10-1 21:17 编辑

win.update()相当于刷新的窗口的意思,你不刷新,其实动画没动而已,永远刚刚创建时候的样子

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-2 15:50:27 | 显示全部楼层

回帖奖励 +2 鱼币

看上去和3没什么区别
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2018-10-8 11:15:39 | 显示全部楼层

回帖奖励 +2 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-20 10:24:15 | 显示全部楼层

回帖奖励 +2 鱼币

来学习下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-20 17:26:56 | 显示全部楼层

来学习下,等待大牛解答
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 09:00:36 | 显示全部楼层

回帖奖励 +2 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-22 09:48:18 | 显示全部楼层

回帖奖励 +2 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-22 10:49:57 | 显示全部楼层

回帖奖励 +2 鱼币

来看看,学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 13:56:44 | 显示全部楼层
路过,看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-24 15:16:16 | 显示全部楼层

回帖奖励 +2 鱼币

看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-22 15:30:30 | 显示全部楼层

回帖奖励 +2 鱼币

共同学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-18 14:00:58 | 显示全部楼层

回帖奖励 +2 鱼币

没有大佬解答么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-18 19:56:22 | 显示全部楼层

回帖奖励 +2 鱼币

我不会
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-30 22:21:44 | 显示全部楼层

回帖奖励 +2 鱼币

用after
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-2 20:59:48 | 显示全部楼层    本楼为最佳答案   

回帖奖励 +2 鱼币

本帖最后由 惊晓欲仙 于 2025-2-2 21:07 编辑

首先进行问题分析
1. sleep 函数不加 win.update() 会卡死
在 Tkinter 中,主事件循环负责处理各种用户交互和界面更新。当你使用 time.sleep() 时,程序会暂停执行,这会阻塞主事件循环。也就是说,在 sleep 期间,Tkinter 无法处理新的事件(如鼠标点击、窗口重绘等),导致界面看起来像是卡死了。而 win.update() 会手动更新 Tkinter 的事件循环,使得在 sleep 之前界面有机会处理待处理的事件,避免卡死。
2. 递归和 while 循环的问题
递归:递归调用 blink 函数会不断增加调用栈的深度。当循环次数增多时,会导致栈溢出错误,因为 Python 对递归深度有一定的限制。
while 循环:while 循环同样会阻塞主事件循环,使得 Tkinter 无法正常处理其他事件。当你强行关闭窗口时,由于主事件循环被阻塞,Tkinter 无法正确处理窗口关闭事件,从而抛出 TclError 异常。
下面是解决方法(我用after来解决,使用 after 方法可以避免阻塞主事件循环,从而解决界面卡死和异常抛出的问题。同时,由于不会无限递归或使用 while 循环,也不会出现栈溢出的问题。但可以等会小甲鱼哦,甲鱼有可能有其他方法)
import tkinter as tk
import time

class BlinkAnimation:
    def __init__(self, win):
        self.win = win
        self.blinkFlag = False
        # 创建一个按钮
        self.button = tk.Button(win, text="Toggle Blink", command=lambda: self.normal(win))
        self.button.pack()

    def blink(self):
        if self.blinkFlag:
            # 这里是各种操作,例如更新标签文本
            # 示例:假设这里有一个标签
            label = tk.Label(self.win, text="Blinking...")
            label.pack()
            # 使用 after 方法在 5 毫秒后再次调用 blink 函数
            self.win.after(5, self.blink)

    def normal(self, win):
        if self.blinkFlag == False:
            self.blinkFlag = True
            self.blink()
        elif self.blinkFlag == True:
            self.blinkFlag = False

if __name__ == "__main__":
    root = tk.Tk()
    app = BlinkAnimation(root)
    root.mainloop()

有用点点支持,多多评分哦

评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
ydwb + 1 + 1 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-2 21:06:09 | 显示全部楼层
有用的话评个分吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-2 21:06:45 | 显示全部楼层
惊晓欲仙 发表于 2025-2-2 20:59
首先进行问题分析
1. sleep 函数不加 win.update() 会卡死
在 Tkinter 中,主事件循环负责处理各种用户 ...

大家有用的话评个分吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-2-24 02:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表