【问题标题】:TypeError: Can't convert 'DoubleVar' object to str implicitlyTypeError:无法将“DoubleVar”对象隐式转换为str
【发布时间】:2017-08-31 12:48:05
【问题描述】:

我正在创建一个简单的 GUI 程序来测量某个事件的时间。我收到一个错误:

/usr/bin/python3.5 /home/cali/PycharmProjects/str8/str8.py Traceback (最近一次通话最后):文件 “/home/cali/PycharmProjects/str8/str8.py”,第 51 行,在 app = App(root) 文件“/home/cali/PycharmProjects/str8/str8.py”,第 22 行,在 init 标签(self, text=measurement + ":" + self.counters[measurement], font='Verdana 8').grid(row=i+1, column=0, sticky=W) TypeError: Can't 将 'DoubleVar' 对象隐式转换为 str

进程以退出代码 1 结束

我试过这个:

Label(self, text=measurement + ": " + str(self.counters[measurement]), font='Verdana 8').grid(row=i+1, column=0, sticky=W)

...但它给了我这个:

GUI program

这是我所做的:

# str8.py
#   Program to count time from a certain event

from tkinter import *
from datetime import *


class App(Frame):

    def __init__(self, *args, **kwargs):

        Frame.__init__(self, *args, **kwargs)
        self.grid(sticky = N + W + E + S)

        Label(self, text = 'You have been STR8 for:', font="Verdana 8 bold").grid(row=0, sticky=W)

        self.counters = dict()
        measurements = [ 'Years', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds' ]

        for i, measurement in enumerate(measurements):
            self.counters[measurement] = DoubleVar()
            Label(self, text=measurement + ": " + self.counters[measurement], font='Verdana 8').grid(row=i+1, column=0, sticky=W)
            self.counters[measurement].set(0)

        Button(self,
               text="EXIT",
               font="Verdana 8",
               height=1,
               width=19,
               command=quit).grid(row=7, column=0)

        self.increment()

    def increment(self):
        event = datetime(2017, 4, 4, 0, 0, 0)
        today = datetime.now()

        str8 = today - event
        self.counters['Seconds'].set(round(str8.total_seconds(), 2))
        self.counters['Minutes'].set(round(str8.total_seconds()/ 60, 2))
        self.counters['Hours'].set(round(str8.total_seconds() / 3600, 2))
        self.counters['Days'].set(round(str8.total_seconds() / (3600 * 24), 2))
        self.counters['Weeks'].set(round(str8.total_seconds() / (3600 * 24 * 7), 2))
        self.counters['Years'].set(round(str8.total_seconds() / (3600 * 24 * 7 * 52), 2))

        self.after(1000, self.increment)


if __name__ == '__main__':
    root = Tk()
    app = App(root)
    root.title("STR8")
    root.resizable(width=False, height=False)
    app.mainloop()

【问题讨论】:

    标签: python tkinter label


    【解决方案1】:

    标签可以使用 text 参数显示一些文本,或者它可以使用 textvariable 参数显示来自 tkinter 变量(如 DoubleVar)的值。它不能两者兼得。要么使用这个:

    lbl = Label(self, text=measurement + ": ", font='Verdana 8')
    lbl.grid(row=i+1, column=0, sticky=W)
    

    或者这个:

    lbl = Label(self, textvariable=self.counters[measurement], font='Verdana 8')
    lbl.grid(row=i+1, column=0, sticky=W)
    

    编辑:解决您的问题的方法是制作自己的标签类型,可以同时处理这两种情况:

    import tkinter as tk
    from datetime import datetime
    
    class FormatLabel(tk.Label):
        '''A new type of Label widget that allows both a text and textvariable'''
        def __init__(self, master=None, **kwargs):
            self.textvariable = kwargs.pop('textvariable', tk.StringVar(master))
            self.text = kwargs.pop('text', '{}')
            self.textvariable.trace('w', self.update_text)
            tk.Label.__init__(self, master, **kwargs)
    
        def update_text(self, *args):
            self.config(text=self.text.format(self.textvariable.get()))
    
    class App(tk.Frame):
        def __init__(self, master=None, **kwargs):
            tk.Frame.__init__(self, master, **kwargs)
    
            lbl = tk.Label(self, text = 'You have been STR8 for:', font="Verdana 8 bold")
            lbl.grid(row=0, sticky=tk.W)
    
            self.counters = dict()
            measurements = [ 'Years', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds' ]
    
            for i, measurement in enumerate(measurements):
                self.counters[measurement] = tk.DoubleVar()
                lbl = FormatLabel(self,
                    text=measurement + ": {:.2f}", # set the rounding here
                    textvariable = self.counters[measurement],
                    font='Verdana 8')
                lbl.grid(row=i+1, column=0, sticky=tk.W)
                self.counters[measurement].set(0)
    
            btn = tk.Button(self,
                   text="EXIT",
                   font="Verdana 8",
                   height=1,
                   width=19,
                   command=quit)
            btn.grid(row=7, column=0)
    
            self.increment()
    
        def increment(self):
            event = datetime(2017, 4, 4, 0, 0, 0)
            today = datetime.now()
    
            str8 = (today - event).total_seconds()
            self.counters['Seconds'].set(str8)
            self.counters['Minutes'].set(str8 / 60.)
            self.counters['Hours'].set(str8 / 3600.)
            self.counters['Days'].set(str8 / (3600. * 24))
            self.counters['Weeks'].set(str8 / (3600. * 24 * 7))
            self.counters['Years'].set(str8 / (3600. * 24 * 7 * 52))
    
            self.after(1000, self.increment)
    
    def main():
        root = tk.Tk()
        app = App(root)
        app.pack()
        root.title("STR8")
        root.resizable(width=False, height=False)
        app.mainloop()
    
    if __name__ == '__main__':
        main()
    

    请注意,我还修复了您代码的其他一些部分;最值得注意的是,您不应使用通配符导入 (from module import *),不应在定义它们的同一行上布局小部件,并且应尽量不要重复代码。

    【讨论】:

    • 然后我会得到标签之间的巨大差距,这就是我试图将这两个标签组合成一个标签的原因。来吧,我的问题的解决方法一定很简单。
    • 简单,不。但可行。我编辑了我的答案以向您展示一种方式。
    • 非常感谢先生,这就是精神!
    • ...当涉及到导入时,这是为什么呢?如你所见,我还是个新手。
    • 为什么没有通配符导入?简而言之,它会变得混乱且难以快速阅读。基本上,在您的代码中,读者无法知道“标签”是在代码中定义还是从通配符导入之一定义的。另外,你不知道你在导入什么。如果 datetime 决定实现一个常量“W”怎么办?由于该导入排在第二位,它将覆盖来自 tkinter 的“W”。你会得到错误并且非常沮丧,因为你认为你在使用tkinter.W,而实际上你在使用datetime.W。它也反对 PEP8。
    猜你喜欢
    • 2012-11-19
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2018-09-12
    • 2018-12-07
    • 1970-01-01
    相关资源
    最近更新 更多