【问题标题】:Tkinter multiple operationsTkinter 多重操作
【发布时间】:2012-08-19 06:43:08
【问题描述】:

我的问题与此类似:Python TKinter multiple operations。但是,提供的答案对我没有帮助,因为它指向了一篇包含可能使用的功能列表的文章。我想看看解决方案的实际实现。

我的问题:我的框架上有两个按钮。只要将切换变量设置为true,一个按钮就会调用“执行”功能。第二个按钮将切换值设置为 False。我希望“执行”功能在按下执行按钮后继续运行,但在按下第二个(切换为假)按钮时停止。但是,一旦我按“执行”,框架就会卡住。我理解它是因为回调。我怎样才能解决这个问题?这是我的示例代码:

from Tkinter import *
from time import sleep

class App:

    def __init__(self, master):

        self.toggle = False
        frame = Frame(master)
        frame.pack()

        self.exeButton = Button(frame, text="Execute", fg="blue", command=self.execute)
        self.exeButton.pack(side=LEFT)

        self.tOffButton = Button(frame, text="Toggle Off", command=self.toggleOff)
        self.tOffButton.pack(side=LEFT)

    def execute(self):
        self.toggle = True
        while(self.toggle):
            print "hi there, everyone!"
            sleep(2)

    def toggleOff(self):
    self.toggle = False

root = Tk()
app = App(root)
root.mainloop()

【问题讨论】:

    标签: python user-interface button tkinter frame


    【解决方案1】:

    简短的回答,你不能完全按照你的意愿去做。 Tkinter 是单线程的——当你调用sleep(2) 时,它会按照你的要求做:它会休眠。

    如果您的目标是在布尔标志设置为 True 的情况下每 2 秒执行一次,您可以使用 after 来安排将来运行的作业。如果该作业还使用 after 来(重新)调度自身,那么您就有效地创建了一个无限循环,其中实际的循环机制是事件循环本身。

    我已经获取了您的代码并进行了一些细微的修改,以向您展示如何连续执行某些事情,直到一个标志告诉它停止。我冒昧地将“切换”重命名为“运行”以使其更容易理解。我也只使用一种方法来打开和关闭执行。

    from Tkinter import *
    from time import sleep
    
    class App:
    
        def __init__(self, master):
    
            self.master = master
            self.running = False
            frame = Frame(master)
            frame.pack()
    
            self.exeButton = Button(frame, text="Execute", fg="blue", 
                command=lambda: self.execute(True))
            self.exeButton.pack(side=LEFT)
    
            self.tOffButton = Button(frame, text="Toggle Off", 
                command=lambda: self.execute(False))
            self.tOffButton.pack(side=LEFT)
    
        def execute(self, running=None):
            if running is not None:
                self.running = running
            if self.running:
                print "hi there, everyone!"
                self.master.after(2000, self.execute)
    
    root = Tk()
    app = App(root)
    root.mainloop()
    

    【讨论】:

    • 如果我们每次遇到问题时都有一个小窍门,而答案基本上是:“不要使用sleep,而是使用Widget.after”,我们可能会得到一美元现在:^)。
    • 这是另一种情况,您的钱可能会多出 10 倍:我是 GUI 编程新手。或者,我是 python 新手。另外,我以前从未使用过 Tkinter。
    • 问题:如果'execute'函数从不同的导入类调用另一个函数并且导入的函数使用睡眠会发生什么?我假设我会再次遇到同样的问题?
    • 是的,你也会遇到同样的问题。睡眠导致整个线程进入睡眠状态。几乎每个 GUI 工具包的一个好的经验法则是永远不要使用睡眠。这不是 GUI 应用程序的工作方式。它们需要保持活动状态,以便为重绘请求、按键等事件提供服务。
    • 当然你可以封装一个 GUI 库使其成为线程安全的,然后交替使用线程...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 2012-07-09
    • 2016-10-28
    • 2015-07-28
    • 2021-07-30
    • 1970-01-01
    相关资源
    最近更新 更多