具有多个类和Tkinter的Python属性错误
我正在尝试使用Tkinter创建一个gui,它获取用户名和密码,连接到远程服务器并执行一个功能。我拼凑了一些乱七八糟的代码,它或多或少起了作用,但当我试图在一个整洁的模块中重新创建它时,它坏了。这可能是一个新手python错误,但我无法发现它。编辑:为了澄清,当它工作时,唯一的类是setupGui,任何方法都在该类下。既然我已经将gui与方法分离,它就不起作用了具有多个类和Tkinter的Python属性错误,python,user-interface,attributes,tkinter,syntax-error,Python,User Interface,Attributes,Tkinter,Syntax Error,我正在尝试使用Tkinter创建一个gui,它获取用户名和密码,连接到远程服务器并执行一个功能。我拼凑了一些乱七八糟的代码,它或多或少起了作用,但当我试图在一个整洁的模块中重新创建它时,它坏了。这可能是一个新手python错误,但我无法发现它。编辑:为了澄清,当它工作时,唯一的类是setupGui,任何方法都在该类下。既然我已经将gui与方法分离,它就不起作用了 class setupGui(object): def __init__(self, parent): ##omit
class setupGui(object):
def __init__(self, parent):
##omited general frame stuff
self.userIn = ttk.Entry(self.topFrame, width = 20)
self.userIn.grid(row = 1, column = 1)
self.passIn = ttk.Entry(self.topFrame, width = 20, show ="*")
self.passIn.grid(row = 2, column = 1)
#Buttons
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
self.setupbtn.grid(row = 3, column = 0, pady = 10)
class setup(object):
def__init__(self):
self.userName = setupGui.userIn.get()
self.userPass = setupGui.passIn.get()
def startSetup(self):
self.another_related_fucntion # about 4 related functions actually
if __name__ == '__main__':
root = Tk()
gui = setupGui(root)
root.mainloop()
如果我没有将命令附加到按钮上,那么一切都可以正常工作(但很明显,除了看起来很漂亮外,我确实做了下蹲)。当我附加命令时,我得到以下错误:
Traceback (most recent call last):
File "macSetup.py", line 211, in <module>
gui = setupGui(root)
File "macSetup.py", line 45, in __init__
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
File "macSetup.py", line 69, in __init__
self.userName = setupGui.userIn.get()
AttributeError: type object 'setupGui' has no attribute 'userIn'
回溯(最近一次呼叫最后一次):
文件“macSetup.py”,第211行,在
gui=设置gui(根目录)
文件“macSetup.py”,第45行,在_init中__
self.setupbtn=ttk.Button(self.topFrame,text=“启动设置”,command=Setup().startSetup())
文件“macSetup.py”,第69行,在_init中__
self.userName=setupGui.userIn.get()
AttributeError:类型对象“setupGui”没有属性“userIn”
类setupGui
本身没有属性userIn
在
setupGui
的\uuuuu init\uuuuu
方法中,将属性赋予实例,而不是类。在代码中,userIn
设置为setupGui
对象的实例变量,而不是setupGui
类本身的属性
最简单的解决方案是合并setupGui
和setup
类,将startSetup
作为setupGui
的一种方法移入,然后在初始化setupbtn
时使用command=self.startSetup
——这将startSetup
作为绑定方法调用,因此,self
应该引用setupGui
对象,然后您可以在上使用该对象,例如self.userIn.get()
和self.passIn.get()
如果您希望将setup
类中的逻辑保留在setupGui
类之外,可以这样将其分离:
class setup(object):
def __init__(self, username, userpass):
self.userName = username
self.userPass = userpass
def startSetup(self):
# as before
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup)
然后将此方法添加到setupGui
类:
def dosetup(self):
setup(self.userIn.get(), self.passIn.get()).startSetup()
并使用
command=self.dosetup
实例化按钮。(我个人会将设置
类设置为一个独立的函数,但我不知道启动设置
例程实际上有多复杂,因此我认为您有充分的理由将其设置为类。)命令
属性引用函数,但是您正在调用函数并将结果提供给命令
属性。最终的结果是,您在创建按钮时调用设置函数,而不是在单击按钮时。事情还没有完全初始化,所以您会得到错误
您正在这样做:
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
。。。当你应该这样做的时候:
class setup(object):
def __init__(self, username, userpass):
self.userName = username
self.userPass = userpass
def startSetup(self):
# as before
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup)
注意startSetup
上缺少尾随的()
如果在单击按钮之前不想实例化设置
,则有两种选择。可以说,最好的方法是创建一种方法:
def _launch_setup(self):
setup().setupGui()
...
self.setupbtn = ttk.Button(..., command=self._launch_setup)
您也可以使用lambda,但在本例中,我建议使用命名方法。我最初就是这样设置的。我通常不喜欢将函数与GUI混合在一起。在Java中,我甚至可以将它们放在单独的包中。我尝试将self.userName=setupGui.userIn.get()更改为self.userName=setupGui(root.userIn.get(),但出现了一个疯狂的递归错误。我也尝试用gui代替root(因为它在main中定义),但它说它未定义。哪一条路线更像蟒蛇路线?请参见编辑。我想这对你有用。(实际上,请看最近的编辑,因为我第一次把
dosetup
搞砸了。)