Python tkinter变量在另一个类中

Python tkinter变量在另一个类中,python,class,methods,tkinter,ttk,Python,Class,Methods,Tkinter,Ttk,Python 3.1,tkinter/ttk 我写了一些非常简单的东西,试图理解tkinter链接到小部件的变量如何存储在小部件的不同类中。代码如下 问题: 1为什么按下按钮不改变标签 我需要这么多的自我吗?每个方法中的变量是否可以无需自身管理。一开始 希望这个答案对其他tkinter新手来说是一个有用的学习练习 from tkinter import * from tkinter.ttk import * root = Tk() class Store: def __init__

Python 3.1,tkinter/ttk

我写了一些非常简单的东西,试图理解tkinter链接到小部件的变量如何存储在小部件的不同类中。代码如下

问题:

1为什么按下按钮不改变标签

我需要这么多的自我吗?每个方法中的变量是否可以无需自身管理。一开始

希望这个答案对其他tkinter新手来说是一个有用的学习练习

from tkinter import *
from tkinter.ttk import *

root = Tk()

class Store:

    def __init__(self):
        self.v = IntVar()
        self.v.set(0)

    def set(self, v):
        self.v.set(v)

class Main:

    def __init__(self):

        self.counter = 0

        self.label = Label(root, textvariable = a.v)
        self.label.pack()

        self.button = Button(root, command = self.counter, text = '+1')
        self.button.pack()

    def counter(self):

        self.counter = self.counter + 1
        a.set(self.counter)

a = Store()
b = Main()

root.mainloop()

如果我是你,我会这样做:

import tkinter

root = tkinter.Tk()
var  = tkinter.IntVar()

label  = tkinter.Label(root, textvariable=var)
button = tkinter.Button(root, command=lambda: var.set(var.get() + 1), text='+1')

label.pack()
button.pack()

root.mainloop()
更新:

但是,如果您坚持对两个类执行此操作,其中第一个类只是一个毫无意义的接口,那么我会这样做:

import tkinter

class Store:
    def __init__(self):
        self.variable = tkinter.IntVar()

    def add(self, value):
        var = self.variable
        var.set(var.get() + value)
        return var.get()

class Main(tkinter.Tk):
    def __init__(self, *args, **kwargs):
        tkinter.Tk.__init__(self, *args, **kwargs)
        var = Store()
        self.label  = tkinter.Label(self, textvariable=var.variable)
        self.button = tkinter.Button(self, command=lambda: var.add(1), text='+1')
        self.label.pack()
        self.button.pack()


root = Main()
root.mainloop()
正如您可能注意到的,在您的版本中,我在两次使用了IntVar的get和set方法,我是通过我们制作的存储接口来实现的,因此您不需要使用像self.counter这样的新变量,因为我们实例化的变量正在存储数据

我使用的另一个东西是lambda表达式,而不是完整的函数定义,因为我们只想获取当前值,向其添加1,并将其存储为新值


在我的版本中,Main类是原始tkinter.Tk类的一个子类-这就是为什么我在Main的uu init uu方法中调用它的u init u方法。

如果我是你,我会这样做:

import tkinter

root = tkinter.Tk()
var  = tkinter.IntVar()

label  = tkinter.Label(root, textvariable=var)
button = tkinter.Button(root, command=lambda: var.set(var.get() + 1), text='+1')

label.pack()
button.pack()

root.mainloop()
更新:

但是,如果您坚持对两个类执行此操作,其中第一个类只是一个毫无意义的接口,那么我会这样做:

import tkinter

class Store:
    def __init__(self):
        self.variable = tkinter.IntVar()

    def add(self, value):
        var = self.variable
        var.set(var.get() + value)
        return var.get()

class Main(tkinter.Tk):
    def __init__(self, *args, **kwargs):
        tkinter.Tk.__init__(self, *args, **kwargs)
        var = Store()
        self.label  = tkinter.Label(self, textvariable=var.variable)
        self.button = tkinter.Button(self, command=lambda: var.add(1), text='+1')
        self.label.pack()
        self.button.pack()


root = Main()
root.mainloop()
正如您可能注意到的,在您的版本中,我在两次使用了IntVar的get和set方法,我是通过我们制作的存储接口来实现的,因此您不需要使用像self.counter这样的新变量,因为我们实例化的变量正在存储数据

我使用的另一个东西是lambda表达式,而不是完整的函数定义,因为我们只想获取当前值,向其添加1,并将其存储为新值


在我的版本中,Main类是原始tkinter.Tk类的一个子类-这就是为什么我在Main的uu init uu方法中调用它的uu init uu方法。

您的问题是既有一个方法,又有一个名为counter的变量。单击该按钮时,不会调用函数,因此不会设置变量。创建按钮时,tkinter认为self.counter是一个变量,而不是一个命令

这个特殊问题的解决方案是重命名函数或变量。然后它应该像你期望的那样工作

要回答关于过多self的问题:您需要使用self,以便python知道您所引用的对象应该在对象的特定实例中的任何地方都可用。所以,是的,如果你想引用函数之外的变量,你需要所有这些self

至于自我在定义方法时,这些也是必要的。当您执行object.method时,python将自动发送对该对象的引用,作为方法的第一个参数,以便该方法明确知道正在对哪个方法执行操作


如果您想更多地了解self的用法,这里有一个与self相关的特定问题:

您的问题是您同时拥有一个名为counter的方法和变量。单击该按钮时,不会调用函数,因此不会设置变量。创建按钮时,tkinter认为self.counter是一个变量,而不是一个命令

这个特殊问题的解决方案是重命名函数或变量。然后它应该像你期望的那样工作

要回答关于过多self的问题:您需要使用self,以便python知道您所引用的对象应该在对象的特定实例中的任何地方都可用。所以,是的,如果你想引用函数之外的变量,你需要所有这些self

至于自我在定义方法时,这些也是必要的。当您执行object.method时,python将自动发送对该对象的引用,作为方法的第一个参数,以便该方法明确知道正在对哪个方法执行操作


如果你想更多地了解self的用法,这里有一个与self相关的特定问题:

你的答案似乎没有回答被问到的问题。这个问题是专门针对多个类提出的。另外,你在没有任何解释的情况下编写了一些代码。如果有人只是在学习Tkinter,他们将很难理解您以不同的方式解决了这个问题。我修正了我的答案,尽管@BryanOakley我不认为我必须解释我的简短版本,因为它唯一的魔力是lambda表达式,它不是Tkinter,而是Python问题。无论如何,把我的代表还给我:当回答那些没有经验的人的问题时,解释是必要的,即使是简短的回答。还有什么别的

要知道问题的解决方案是或不是使用lambda,或是删除类,或是使用或不使用self,或是完全其他什么?他们对这些东西一无所知,所以当你给他们几行代码时,他们很可能会得出结论,类不应该与tkinter一起使用,即使这不是你想说的重点。实际上我解释了我的答案,添加了两个类的版本,而你仍然没有删除-1。。请向我解释一下,布莱恩·奥克利!我没有投反对票,但我不会投反对票,因为你没有回答被问到的问题。你说你不认为这个解释是必要的,我只是想解释一下为什么我认为它是必要的。你的回答似乎没有回答被问到的问题。这个问题是专门针对多个类提出的。另外,你在没有任何解释的情况下编写了一些代码。如果有人只是在学习Tkinter,他们将很难理解您以不同的方式解决了这个问题。我修正了我的答案,尽管@BryanOakley我不认为我必须解释我的简短版本,因为它唯一的魔力是lambda表达式,它不是Tkinter,而是Python问题。无论如何,把我的代表还给我:当回答那些没有经验的人的问题时,解释是必要的,即使是简短的回答。否则,他们怎么知道问题的解决方案是或不是使用lambda,或是删除类,或是使用或不使用self,或是完全其他什么?他们对这些东西一无所知,所以当你给他们几行代码时,他们很可能会得出结论,类不应该与tkinter一起使用,即使这不是你想说的重点。实际上我解释了我的答案,添加了两个类的版本,而你仍然没有删除-1。。请向我解释一下,布莱恩·奥克利!我没有投反对票,但我不会投反对票,因为你没有回答被问到的问题。你说你不认为这个解释是必要的,我只是想解释一下为什么我这么认为。我不认为这个答案对学习实用和干净的代码有帮助…@PeterVaro:这对我来说似乎是报复性的否决票,尽管我并不真的在乎声誉。您是对的,它对学习实用和干净的代码没有特别的帮助,但这并不是我们要问的问题。用户特别询问为什么在给定代码中按下按钮不起作用,我回答了这个问题。我认为说这不是一个有用的答案是不诚实的,而且可能会给OP留下这样的印象:我的答案在某种程度上是错误的,尽管它正确地说明了代码的实际问题。就像我的答案一样@Bryan Oakley!一旦你从我的答案中删除-1,我也会对你这样做。我也不在乎销售代表,但既然我的答案是两个版本都适用,而且都是正确、干净和实用的,我不知道你为什么首先给我-1,而不是在评论中给我一个警告,或者诸如此类的东西。@PeterVaro:我不讨价还价。我投有帮助的票,我不投没有帮助的票,我不会改变我的投票,这样其他人就会取消对我的反对票。我希望你也会这么做,这就是投票系统有用的原因。因为某人投了你的反对票而投反对票对任何人都没有帮助。@PeterVaro:你和我一样。不,你的答案不是。问题的一部分是为什么按下按钮不改变标签?而你从未接近解决这个问题。你也没有回答关于自我的问题。您确实提供了一个很好的替代解决方案,但这并不是所要求的。如果你这样做了,并且回答了被问到的实际问题,你肯定会得到我的支持票,尽管你出于恶意投票反对我。我不认为这个答案有助于学习实用和干净的代码…@PeterVaro:对我来说,这看起来像是报复性的反对票,尽管我并不真正关心声誉。您是对的,它对学习实用和干净的代码没有特别的帮助,但这并不是我们要问的问题。用户特别询问为什么在给定代码中按下按钮不起作用,我回答了这个问题。我认为说这不是一个有用的答案是不诚实的,而且可能会给OP留下这样的印象:我的答案在某种程度上是错误的,尽管它正确地说明了代码的实际问题。就像我的答案一样@Bryan Oakley!一旦你从我的答案中删除-1,我也会对你这样做。我也不在乎销售代表,但既然我的答案是两个版本都适用,而且都是正确、干净和实用的,我不知道你为什么首先给我-1,而不是在评论中给我一个警告,或者诸如此类的东西。@PeterVaro:我不讨价还价。我投有帮助的票,我投没有帮助的票,我不改变我的票,这样其他人就会删除n
对我投反对票。我希望你也会这么做,这就是投票系统有用的原因。因为某人投了你的反对票而投反对票对任何人都没有帮助。@PeterVaro:你和我一样。不,你的答案不是。问题的一部分是为什么按下按钮不改变标签?而你从未接近解决这个问题。你也没有回答关于自我的问题。您确实提供了一个很好的替代解决方案,但这并不是所要求的。如果你这样做了,并且回答了被问到的实际问题,你肯定会得到我的支持票,尽管你出于恶意投了我的反对票。