Tkinter回调函数导致ValueError

时间:2013-10-26 19:03:53

标签: python callback tkinter

我遇到了tkinter trace方法的回调函数问题。我想有2个条目,每个条目的值取决于另一个条目的值。因此,如果我更改1的值,则更改另一个的值。这是一些简单的代码:

from tkinter import *

class main():

    def __init__(self, master):

        self.a = DoubleVar(value=2.0)
        self.b = DoubleVar()
        self.b.trace("w",self.calc_c)
        self.c = DoubleVar()
        self.c.trace("w",self.calc_b)

        Entry(master,textvariable=self.b).grid(row=0,column=0)
        Entry(master,textvariable=self.c).grid(row=0,column=1)

    def calc_b(self,name,index,mode):
        self.b.set(self.c.get()/self.a.get())

    def calc_c(self,name,index,mode):
        self.c.set(self.b.get()*self.a.get())


root = Tk()

prog = main(root)

root.mainloop()

程序实际上正在运行,返回正确的值,但也会产生错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib64/python3.3/tkinter/__init__.py", line 1475, in __call__
    return self.func(*args)
  File "/home/anze/foo.py", line 22, in calc_c
    self.c.set(self.b.get()*self.a.get())
  File "/usr/lib64/python3.3/tkinter/__init__.py", line 332, in get
    return getdouble(self._tk.globalgetvar(self._name))
ValueError: could not convert string to float: 

有人可以解释一下这个错误的含义吗?

谢谢!

3 个答案:

答案 0 :(得分:0)

我相信您的问题是您将self.c绑定到Entry小部件:

Entry(master,textvariable=self.c).grid(row=0,column=1)

但是,textvariable应设置为Tkinter.StringVar。如何创建一个新变量来保存Entry的字符串值,然后在calc方法中进行转换:

from tkinter import *

class main():

    def __init__(self, master):

        self.a = DoubleVar(value=2.0)
        self.b = DoubleVar()
        self.b.trace("w",self.calc_c)
        self.c = DoubleVar()
        self.c_str = StringVar()
        self.c.trace("w",self.calc_b)

        Entry(master,textvariable=self.b).grid(row=0,column=0)
        Entry(master,textvariable=self.c_str).grid(row=0,column=1)

    def calc_b(self,name,index,mode):
        self.c.set(float(self.c_str.get()))
        self.b.set(self.c.get()/self.a.get())

    def calc_c(self,name,index,mode):
        self.c.set(self.b.get()*self.a.get())


root = Tk()

prog = main(root)

root.mainloop()

请注意,您可能希望对其他条目执行相同的操作。

答案 1 :(得分:0)

我认为问题在于窗口小部件是一个条目,它以字符串作为输入,而您的值是DoubleVar,但您没有进行任何验证以防止用户输入无效值。

只要输入值是浮点数,您的代码就会起作用。在输入无效值后,在get()calc_c中调用calc_b时,tkinter会尝试将Entry中的字符串转换为float,失败并抛出ValueError异常。

您可以使用try-except块捕获异常。在try块中,您放置了可能引发异常的代码。 except块定义捕获异常时发生的情况。您还可以使用else块来定义未捕获异常时发生的情况。

以下是calc_c的一个简单示例(没有else块),它恢复了以前的值(calc_b需要以类似的方式修改):

def calc_c(self,name,index,mode):
    try:
        self.c.set(self.b.get()*self.a.get())
    except ValueError:
        # here you can either complain to the user (message-box...) 
        # or just restore the last value using the other entry like so:
        self.b.set(self.c.get()/self.a.get())

答案 2 :(得分:0)

我使用Tk.scale(... resolution=0.1, ...)发生了类似的错误。 如果在同一个脚本中使用了matplotlib,则缩放后的十进制数字会使用,而不是.来编写,并在getdouble()中导致错误。

我找到了一种解决方法,将os(kubuntu14.04)的区域设置从德语更改为美国,.为默认小数分隔符。

它不能令人满意的解决方案,但可能有助于找到问题。