代码之家  ›  专栏  ›  技术社区  ›  jason

tkinter:在脚本运行时单击其他按钮的能力

  •  0
  • jason  · 技术社区  · 6 年前

    from Tkinter import *
    import Tkinter as tk
    import time
    
    def function1():
        time.sleep(60)
        print 'function1'
    
    
    def function2():
        time.sleep(60)
        print 'function2'
    
    root = Tk()
    
    w = 450 # width for the Tk root
    h = 500# height for the Tk root
    
    frame = Frame(root, width=w,height =h)
    button1=Button(frame, text = 'function 1',fg='black',command=function1).grid(row=1,column=1) 
    button2=Button(frame, text = 'function 2',fg='black',command=function2).grid(row=1,column=2) 
    
    frame.pack()
    root.mainloop()
    

    我想点击 function2 function1 仍在运行

    1 回复  |  直到 6 年前
        1
  •  5
  •   abarnert    6 年前

    如果触发一个运行需要1分钟的回调,那么1分钟内不会返回到主循环,因此GUI无法响应任何内容。

    有两种常见的解决方案。


    def function1():
        time.sleep(60)
        print 'function1'
    
    def function1_background():
        t = threading.Thread(target=function1)
        t.start()
    
    button1 = Button(frame, text='function 1', fg='black', command=function1_background)
    

    这很简单,但它只在您的代码纯粹是做后台工作,而不是接触任何tkinter小部件时才起作用。


    def 20个额外功能。你不想重复你自己,因为80行重复的样板代码妨碍了你看到重要的代码,还有20次机会在复制粘贴中产生一个愚蠢的错误,这是一个很难追踪的问题,如果你以后决定要改变20个地方,比如说进程而不是线程,这样工作就可以并行化更好,或者是一个由4个线程组成的池,后台任务排队。

    this question 更深入的解释,但简而言之,您可以让Python为您做一些重复的工作。


    定义

    def background(func):
        t = threading.Thread(target=func)
        t.start()
    

    lambda 20独立功能:

    button1 = Button(frame, text='function 1', fg='black', command=lambda: background(function1))
    

    或者,可以使用 partial :

    button1 = Button(frame, text='function 1', fg='black', command=functools.partial(background, function1))
    

    或者,如果不想在后台以外的地方调用函数,可以编写一个decorator并将其应用于每个函数 定义

    def background(func):
        @functools.wraps(func)
        def wrapper():
            t = threading.Thread(target=func)
            t.start()
        return wrapper
    
    @background
    def function1():
        time.sleep(60)
        print 'function1'
    

    def function1(count=60):
        if count > 0:
            time.sleep(0.1)
            frame.after(0, function1, count-0.1)
        else:
            print 'function1'
    
    button1 = Button(frame, text='function 1', fg='black', command=function1)
    

    如果你能找到一个方法的话,这总是有效的。你真正的工作可能不像一个普通的工作那样容易分成0.1秒的部分 sleep(60) 是。