【问题标题】:Tkinter button stays pressedTkinter 按钮保持按下状态
【发布时间】:2018-07-27 18:48:59
【问题描述】:

我正在制作一个使用按钮小部件的 tkinter 代码,但是当我按下按钮时,它会一直被按下,直到按下按钮时执行的功能没有完成。我希望立即释放按钮并执行该功能。 这是一个代码,显示了发生的一个很好的例子:

from tkinter import *
import time
root = Tk()
root.geometry('100x100+100+100') # size/position of root
def callback(): # this function will run on button press
    print('Firing in 3')
    time.sleep(3) # wait for 3 seconds
def main(): #function 'main'
    b = Button(root, text="ᖴIᖇE", width=10,height=2, command=callback)# setting the button
    b["background"] = 'red' #button color will be red
    b["activebackground"] = 'yellow'  #button color will be yellow for the time when the button will not be released
    b.place(x=25,y=25) #placing the button
main() # using function 'main'
mainloop()

【问题讨论】:

  • 你应该使用线程。
  • 按钮卡住取决于代码。如果你真的有睡眠,你应该改用多线程或after。如果实际过程需要很长时间,您可以使用更新方法或多线程。
  • 嗯,你让它睡觉,所以它在睡觉。休眠时无法更新显示。
  • 多线程不是答案。请。
  • tkinter 是单线程的——一次只能做一件事。当你的循环运行时,它不能更新显示。在 stackoverflow 上有很多个问题。

标签: python python-3.x button tkinter


【解决方案1】:

您可以在按下时被阻止的功能内使用threading。这是我对你的修改:

from tkinter import *
import time
import threading

root = Tk()
root.geometry('100x100+100+100')  # size/position of root


def callback():  # this function will run on button press
    def callback2():
        print('Firing in 3')
        time.sleep(3)  # wait for 3 seconds
    threading.Thread(target=callback2).start()


def realcallback():
    print('Firing now')


def main():  # function 'main'
    b = Button(
        root,
        text="Fire",
        width=10,
        height=2,
        command=callback
    )  # setting the button
    b["background"] = 'red'  # button color will be red
    # button color will be yellow for the time when the button will not be released
    b["activebackground"] = 'yellow'
    b.place(x=25, y=25)  # placing the button


main()  # using function 'main'
mainloop()

【讨论】:

    【解决方案2】:

    GUI 程序通常在单个线程中驱动,由正在使用的图形工具包的“主循环”控制。那就是:一个程序通常设置应用程序,并将控制权传递给工具包,该工具包运行一个紧密的循环来回答所有用户(和网络、文件等)事件,以及唯一再次运行的用户代码是在设置阶段编码的回调。

    同时,当您的代码在回调期间运行时,它拥有控件 - 这意味着当您的函数不返回时,工具包将无法响应任何事件。

    必须做的是编写与 GUI 工具包协作的代码 - 也就是说,如果您需要时间间隔的事情,则创建生成进一步回调的事件。在 tkinter 的情况下,这是通过小部件的 .after 方法实现的:在那么多毫秒之后,传递的可调用对象将被运行。另一方面,time.sleep 会在那里停止单个线程,并且事件循环不会运行。

    在你的例子中,你可以简单地写:

    from tkinter import *
    import time
    root = Tk()
    root.geometry('100x100+100+100') # size/position of root
    
    def callback(): # this function will run on button press
        print('Firing in 3')
        root.after(3000, realcallback)
    
    def realcallback():
        print('Firing now!')
    
    def main(): #function 'main'
        b = Button(root, text="ᖴIᖇE", width=10,height=2, command=callback)# setting the button
        b["background"] = 'red' #button color will be red
        b["activebackground"] = 'yellow'  #button color will be yellow for the time when the button will not be released
        b.place(x=25,y=25) #placing the button
    main() # using function 'main'
    mainloop()
    

    【讨论】:

    • 当我在回调函数中使用需要时间的循环时怎么办?
    • 如果你的循环需要时间计算的东西,那么你可以求助于线程。但是,如果“时间”是为游戏对象设置动画,情况就是这样:每个游戏对象都应该“立即”绘制在一个位置,并安排一个 .after 回调在其下一个位置呈现。使用游戏对象的类可以很容易地做到这一点。
    【解决方案3】:

    我想补充:

    from tkinter import *
    import time
    root = Tk()
    root.geometry('100x100+100+100') # size/position of root
    
    def callback(): # this function will run on button press
        root.update() #<- this works for me..
        print('Firing in 3')
        root.after(3000, realcallback)
    
    def realcallback():
        print('Firing now!')
    
    def main(): #function 'main'
        b = Button(root, text="ᖴIᖇE", width=10,height=2, command=callback)# setting the  button
        b["background"] = 'red' #button color will be red
        b["activebackground"] = 'yellow'  #button color will be yellow for the time when the button will not be released
        b.place(x=25,y=25) #placing the button
    main() # using function 'main'
    mainloop()
    

    【讨论】:

    • 感谢您的首次贡献!不过,您的回答可能需要一点润色。我建议尝试在文本部分解释代码示例在做什么以及为什么。另外,我怀疑你的代码所做的是 OP 所追求的:我认为 OP 正在寻找一种方法来运行更长的计算而不阻塞 tkinter 的 UI 线程。
    猜你喜欢
    • 1970-01-01
    • 2020-12-02
    • 2014-06-14
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多