Python 3.4 tkinter checkbutton变量处理不工作/响应

时间:2015-11-14 17:53:09

标签: python python-3.x tkinter

编辑现在已经转移到Python 3.4.3 tkinter - Program freezes on declaration of IntVar or any other tkinter data type,因为这是问题的根源,现在已经解决了。基本上,从来没有说过任何一个" master"在Python 3.x中使用tkinter,它会导致一个无限循环:(。我的完整代码现已被删除,因为它是我的课程作业,并且不希望有人对它进行修改:D EDIT

我对tkinter相对较新,无法查看我出错的地方。我尝试使用StringVar()和常规字符串来获取多个输入字段,以便在启用Checkbutton时禁用。这是问题所在的框架:

class CActivity(tk.Frame):

def Clear(self):
    pass # To be completed

def Today(self):
    if self.todayVar == "ON":
        self.day.configure(state="disabled")
        self.month.configure(state="disabled")
        self.year.configure(state="disabled")
    else:
        self.day.configure(state="normal")
        self.month.configure(state="normal")
        self.year.configure(state="normal")

def createWidgets(self):

    self.title = tk.Label(self)
    self.title["text"] = "Add an Activity"
    self.title["font"] = ("Times New Roman",30)
    self.title["fg"] = "purple"
    self.title.grid(row=0,column=0,sticky="W",padx=5,pady=5)

    self.todayVar = ""

    tk.Label(self,text="Activity Name:",font=("Times New Roman",15)).grid(row=1,column=0,sticky="W",padx=5,pady=5)
    name = tk.Entry(self).grid(row=1,column=1,columnspan=3,sticky="E",padx=5,pady=5)
    tk.Label(self,text="Priority:",font=("Times New Roman",15)).grid(row=2,column=0,sticky="W",padx=5,pady=5)
    priority = tk.Checkbutton(self).grid(row=2,column=1,sticky="W",padx=0,pady=5)
    tk.Label(self,text="Today?",font=("Times New Roman",15)).grid(row=3,column=0,sticky="W",padx=5,pady=5)
    today = tk.Checkbutton(self,onvalue="ON",offvalue="OFF",variable=self.todayVar,command=self.Today).grid(row=3,column=1,sticky="W",padx=0,pady=5) #problem possibly on this line
    tk.Label(self,text="Date (DD/MM/YYYY):",font=("Times New Roman",15)).grid(row=4,column=0,sticky="W",padx=5,pady=5)

    day = tk.Entry(self,width=2).grid(row=4,column=1,sticky="W",padx=2,pady=5)
    month = tk.Entry(self,width=2).grid(row=4,column=2,sticky="W",padx=2,pady=5)
    year = tk.Entry(self,width=4).grid(row=4,column=3,sticky="W",padx=2,pady=5)

    self.clear = tk.Button(self, command=self.Clear)
    self.clear["text"] = "Clear"
    self.clear["font"] = ("Times New Roman",15)
    self.clear["fg"] = "red"
    self.clear.grid(row=7,column=4,sticky="WE",padx=5,pady=5)

    self.back = tk.Button(self)
    self.back["text"] = "Back"
    self.back["font"] = ("Times New Roman",15)
    self.back["fg"] = "red"
    self.back["command"] = self.parent.Menu
    self.back.grid(row=8,column=4,sticky="WE",padx=5,pady=5)

def __init__(self, parent):

    tk.Frame.__init__(self, parent)
    self.pack()
    self.parent = parent
    self.createWidgets()

这里是使用StringVar()而不是标准的Python字符串:

class CActivity(tk.Frame):

def Clear(self):
    pass # To be completed

def Today(self):
    if self.todayVar.get() == "ON":
        self.day.configure(state="disabled")
        self.month.configure(state="disabled")
        self.year.configure(state="disabled")
    else:
        self.day.configure(state="normal")
        self.month.configure(state="normal")
        self.year.configure(state="normal")

def createWidgets(self):

    self.title = tk.Label(self)
    self.title["text"] = "Add an Activity"
    self.title["font"] = ("Times New Roman",30)
    self.title["fg"] = "purple"
    self.title.grid(row=0,column=0,sticky="W",padx=5,pady=5)

    self.todayVar = tk.StringVar()

    tk.Label(self,text="Activity Name:",font=("Times New Roman",15)).grid(row=1,column=0,sticky="W",padx=5,pady=5)
    name = tk.Entry(self).grid(row=1,column=1,columnspan=3,sticky="E",padx=5,pady=5)
    tk.Label(self,text="Priority:",font=("Times New Roman",15)).grid(row=2,column=0,sticky="W",padx=5,pady=5)
    priority = tk.Checkbutton(self).grid(row=2,column=1,sticky="W",padx=0,pady=5)
    tk.Label(self,text="Today?",font=("Times New Roman",15)).grid(row=3,column=0,sticky="W",padx=5,pady=5)
    today = tk.Checkbutton(self,onvalue="ON",offvalue="OFF",variable=self.todayVar,command=self.Today).grid(row=3,column=1,sticky="W",padx=0,pady=5)
    tk.Label(self,text="Date (DD/MM/YYYY):",font=("Times New Roman",15)).grid(row=4,column=0,sticky="W",padx=5,pady=5)

    day = tk.Entry(self,width=2).grid(row=4,column=1,sticky="W",padx=2,pady=5)
    month = tk.Entry(self,width=2).grid(row=4,column=2,sticky="W",padx=2,pady=5)
    year = tk.Entry(self,width=4).grid(row=4,column=3,sticky="W",padx=2,pady=5)

    self.clear = tk.Button(self, command=self.Clear)
    self.clear["text"] = "Clear"
    self.clear["font"] = ("Times New Roman",15)
    self.clear["fg"] = "red"
    self.clear.grid(row=7,column=4,sticky="WE",padx=5,pady=5)

    self.back = tk.Button(self)
    self.back["text"] = "Back"
    self.back["font"] = ("Times New Roman",15)
    self.back["fg"] = "red"
    self.back["command"] = self.parent.Menu
    self.back.grid(row=8,column=4,sticky="WE",padx=5,pady=5)

def __init__(self, parent):

    tk.Frame.__init__(self, parent)
    self.pack()
    self.parent = parent
    self.createWidgets()

在使用标准字符串的情况下,程序运行正常,直到您单击Checkbutton,此时Checkbutton变为灰色,然后程序停止响应。在使用StringVar()的情况下,由于在窗口初始化期间初始化该帧,所以tk窗口根本不加载。感谢您的帮助,如果您想要完整的代码来帮助我找到问题,请告诉我们。

2 个答案:

答案 0 :(得分:0)

以下是正确运行的代码的简化版本:

#!/usr/bin/env python

''' Toggle disable / normal of Tkinter widgets

    Written by PM 2Ring & R. Murray 2015.11.15
    See http://stackoverflow.com/q/33711472/4014959
'''

#Python 3 / Python 2 Tkinter import
try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class CActivity(tk.Frame):
    def today_cb(self):
        if self.todayVar.get():
            state = "disabled"
        else:
            state = "normal"
        #print(state)

        self.day.configure(state=state)
        self.month.configure(state=state)
        self.year.configure(state=state)


    def create_widgets(self):
        title_text = ("Click the 'Today' Checkbutton to\n"
            "disable / enable date Entry widgets")
        title = tk.Label(self, text=title_text)
        title.grid(row=0, column=0, sticky="W", padx=5, pady=5)

        self.todayVar = tk.IntVar()

        tk.Label(self,text="Today").grid(row=1, column=1, 
            sticky="W", padx=0, pady=5)
        today = tk.Checkbutton(self, variable=self.todayVar, 
            command=self.today_cb)
        today.grid(row=2, column=1, sticky="W", padx=0, pady=5)

        #Date Entry widgets
        tk.Label(self,text="Day").grid(row=3, column=1,
            sticky="W", padx=2, pady=5)
        self.day = tk.Entry(self, width=2)
        self.day.grid(row=4, column=1, sticky="W", padx=2, pady=5)

        tk.Label(self,text="Month").grid(row=3, column=2,
            sticky="W", padx=2,pady=5)
        self.month = tk.Entry(self, width=2)
        self.month.grid(row=4, column=2, sticky="W", padx=2, pady=5)

        tk.Label(self,text="Year").grid(row=3, column=3,
            sticky="W", padx=2, pady=5)
        self.year = tk.Entry(self, width=4)
        self.year.grid(row=4, column=3, sticky="W", padx=2, pady=5)


    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.pack()
        self.parent = parent
        self.create_widgets()


if __name__ == '__main__':
    master = tk.Tk()
    master.title("Disable widgets demo")
    frame = CActivity(master)
    master.mainloop()

您的代码存在一些问题。

您的createWidgets方法会将日期Entry小部件保存到本地变量中,例如day,但它们必须属于实例属性,例如{{1因此可以通过self.day的回调方法访问它们。

另一个问题是你在与widget构造函数相同的行上调用Checkbutton方法。该方法返回.grid,所以正在执行

None

day = tk.Entry(self,width=2).grid(row=4,column=1) 设置为无。

如果您不需要保存对窗口小部件的引用,可以在与构造函数相同的行上使用day(或.grid),但是当您使用它时它将无效需要该引用。 :)

我稍微简化了.pack的回调方法,以减少代码重复。我摆脱了Checkbutton构造函数中的onvalue="ON",offvalue="OFF",因为默认的0和1足以完成此任务,恕我直言,(但如果你愿意,可以随意改回:)),因为我们使用的是数字状态,所以我使用Checkbutton而不是字符串或StringVar。

我还要更改方法的名称以符合PEP 8约定。

您仍然对代码中的局部变量与实例变量存在一些混淆。 IntVarday不同,所以你需要解决这个问题,例如,

self.day

需要

day = tk.Entry(self,width=2)
self.day.grid(row=4,column=1,sticky="W",padx=2,pady=5)

另外,请记住Bryan Oakley所说的关于小部件self.day = tk.Entry(self,width=2) self.day.grid(row=4,column=1,sticky="W",padx=2,pady=5) variable属性需要引用Tkinter textvariableStringVar等实例的内容。

答案 1 :(得分:0)

variabletextvariable属性需要引用Tkinter StringVarIntVarDoubleVarBooleanVar的实例。你不能使用普通变量。

其次,您必须使用这些变量的get方法,才能在if语句中对它们进行比较之前检索这些值。

self.todayVar = StringVar()
...
today = tk.Checkbutton(..., variable=self.todayVar, ...)
...
if self.todayVar.get() == "ON":