函数运行时,Python Tkinter禁用按钮

时间:2019-12-06 21:22:43

标签: python-3.x button tkinter

除非执行功能时再次按下按钮,否则以下代码将按预期工作。我尝试禁用该功能中的按钮,并在该功能完成但无法正常工作时重新启用它。我需要做些什么才能使这项工作?

import tkinter as tk
from tkinter import scrolledtext

root = tk.Tk()
root.title('Test Case')
root.geometry('850x300')
root.configure(background='ivory3')

label_fill = tk.Label(root, width = "80", height = "1", bg = 'ivory3')
label_fill.grid(row=1, columnspan=3)

textw = scrolledtext.ScrolledText(root, width=18, height=2)
textw.grid(column=0, row=2, sticky='nsew')
textw.tag_configure('tag-left', justify='left')
textw.config(background='light grey', foreground='green',
             font='arial 60 bold', wrap='word', relief='sunken', bd=5)


def func_ex(count=None):

    btn = tk.Button(state=tk.DISABLED)   

    if count is not None:
        if count <= 31:
            if (count % 3) == 1:
                txt = 'START'
                sleep = 2000               
            if (count % 3) == 2:
                txt = 'HOLD'
                sleep = 5000            
            if (count % 3) == 0:
                txt = 'END'
                sleep = 1000             
            if count == 31:
                txt = 'DONE'
                sleep = 1
            textw.delete('1.0', 'end')
            textw.insert('end', txt, 'tag-left')
            count += 1
            root.after(sleep, lambda: func_ex(count))
    else:
        func_ex(1)

    btn = tk.Button(state=tk.NORMAL)   


btn = tk.Button(root, text='Start Test Case', bg='light grey',
                width=18,font='arial 12', relief='raised', bd=5,
                command=func_ex)
btn = btn.grid(row=0, column=0)

root.mainloop()

2 个答案:

答案 0 :(得分:2)

我为您创建了一个解决方案。我最大的不同是将应用程序放入一个类中。我发现将tkinter应用程序放在一个类中要避免声明顺序问题要容易得多。您遇到了我提到的几个问题,但是如果不将应用程序放在类中,我将找不到创建工作程序的方法。随时问评论中的任何问题。

import tkinter as tk
from tkinter import scrolledtext


class AnApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('Test Case')
        self.root.geometry('850x300')
        self.root.configure(background='ivory3')

        self.label_fill = tk.Label(self.root, width="80", height="1", bg='ivory3')
        self.label_fill.grid(row=1, columnspan=3)

        self.textw = scrolledtext.ScrolledText(self.root, width=18, height=2)
        self.textw.grid(column=0, row=2, sticky='nsew')
        self.textw.tag_configure('tag-left', justify='left')
        self.textw.config(background='light grey', foreground='green',
                          font='arial 60 bold', wrap='word', relief='sunken', bd=5)
        self.btn = tk.Button(self.root)

        self.btn.configure(text='Start Test Case',
                           bg='light grey', width=18,
                           font='arial 12', relief='raised',
                           bd=5, command=self.func_ex)
        self.btn.grid(row=0, column=0)  # grid returns none you had btn = btn.grid therefore your btn object became none

        self.count = 0

    def func_ex(self):
        self.count += 1
        txt = ""  # It is best practice to initialize variables...
        sleep = 0
        self.btn.configure(state=tk.DISABLED)  # you were also creating new btn objects here in your function
        if self.count <= 31:
            if (self.count % 3) == 1:
                txt = 'START'
                sleep = 2000
            if (self.count % 3) == 2:
                txt = 'HOLD'
                sleep = 5000
            if (self.count % 3) == 0:
                txt = 'END'
                sleep = 1000
            if self.count == 31:
                txt = 'DONE'
                sleep = 1
            self.textw.delete('1.0', 'end')
            self.textw.insert('end', txt, 'tag-left')
            self.root.after(sleep, self.func_ex)  # you can not pass a variable to a .after function even using lambda 
            # because it make a recursive function... basically a memory leak from my understanding.
        else:
            self.btn.configure(state=tk.NORMAL)
            self.count = 0

    def run(self):
        self.root.mainloop()


MyApp = AnApp()
MyApp.run()

答案 1 :(得分:0)

查看上面ShayneLoyd的代码中的注释后,我发现了我的代码有问题。如前所述,我正在函数中创建一个新的Button。我通过将btn设置为全局并使用.configure来更新按钮的状态来解决此问题。下面的代码解决了我的原始代码(函数运行时可以多次按下按钮)和ShayneLoyd的代码(函数第一次完成后按下按钮没有任何作用)的问题

这是工作代码

import tkinter as tk
from tkinter import scrolledtext

root = tk.Tk()
root.title('Test Case')
root.geometry('850x300')
root.configure(background='ivory3')

label_fill = tk.Label(root, width = "80", height = "1", bg = 'ivory3')
label_fill.grid(row=1, columnspan=3)

textw = scrolledtext.ScrolledText(root, width=18, height=2)
textw.grid(column=0, row=2, sticky='nsew')
textw.tag_configure('tag-left', justify='left')
textw.config(background='light grey', foreground='green',
             font='arial 60 bold', wrap='word', relief='sunken', bd=5)


def func_ex(count=None):

    global btn
    btn.configure(state=tk.DISABLED)

    if count is not None:

        if count <= 31:
            if (count % 3) == 1:
                txt = 'START'
                sleep = 2000               
            if (count % 3) == 2:
                txt = 'HOLD'
                sleep = 5000            
            if (count % 3) == 0: 
                txt = 'END'
                sleep = 1000             
            if count == 31:
                txt = 'DONE'
                sleep = 1
            textw.delete('1.0', 'end')
            textw.insert('end', txt, 'tag-left')
            count += 1
            root.after(sleep, lambda: func_ex(count))
        elif count == 32:
             btn.configure(state=tk.NORMAL)
    else:
        func_ex(1)


btn = tk.Button(root, text='Start Test Case', bg='light grey',
                width=18,font='arial 12', relief='raised', bd=5,
                command=func_ex)
btn.grid(row=0, column=0) 

root.mainloop()