如何解决tkinter类对象未定义
我对Python相当陌生,这是我的第一个使用tkinter的项目。除了一个例外,我的整个项目工作正常。我已经将tkinter代码构建到一个类中,并且可以正常工作,但是我无法弄清楚如何从类外部调用方法。
在main的以下行上创建对象时,出现NameError:未定义名称“ robotGUI”
class botGUI:
def __init__(self):
#Init Code
def updateStatus(self):
#Code Here
robotGUI = botGUI()
如果我将变量“ robotGUI”初始化为“无”,则代码将运行,但是当我稍后尝试访问其方法之一时,将得到AttributeError:'NoneType'对象没有属性'doSomething'。似乎没有创建robotGUI对象,但我不明白为什么。
我到处搜索,找到了一些接近的答案,但没有什么与这个问题完全相关。我还有很多其他的类在此程序中可以正常工作,因此我确定它与tkinter有关,并且其内部mainloop只是无法指出它。
以下是我大大简化的代码显示的问题:
#!/usr/bin/env python3
#Imports
import socket,select,errno,sys,queue,time,threading,cv2
from tkinter import *
from tkinter import font
from PIL import Image,ImageTk
#GUI
class botGUI:
def __init__(self):
#Create the Window Object and Setup the Window
self.window = Tk()
self.window.geometry("800x480+0+0")
self.window.overrideredirect(True)
self.window.fullScreenState = False
#Code to Generate Gaphics Here .....
#Call Repeating Status Update Script and Start the Main Loop
self.updateStatus()
self.window.mainloop()
def updateStatus(self):
#Code to Handle Updating Screen Objects Here ....
print("Update Status Running")
#Set this function to be called again
self.window.after(1000,lambda: self.updateStatus())
def doSomething(self,myStr):
#Code to change something on the screen ...
print(f"Command: {str(myStr)}")
def doSomethingElse(self,myStr):
#Code to change something on the screen ...
print(f"Command: {str(myStr)}")
#Main Task - Since tKinter is running in the main loop,all of the main loop code is moved to here
def main_loop():
global robotGUI
robotDataReceived = True #This is only for this posting
#Main Loop
while True:
#If Incoming Data from Robot,Get and Process It!
if robotDataReceived:
robotCmdHandler()
#Anti Blocking Delay (Much shorter,set higher for this post)
time.sleep(2)
#Robot Command Handler
def robotCmdHandler():
global robotGUI
#Code to get a command string and process it goes here .....
cmd = "dosomething" #Temporary for this post
#Handle command
if (cmd == "dosomething"):
print("Processing Command")
robotGUI.doSomething("Do This")
if __name__ == '__main__':
global robotGUI
robotGUI = None
#Create and Start Threads
t1 = threading.Thread(target=main_loop,name='t1')
t1.start()
#Create GUI Object
robotGUI = botGUI()
#Wait until threads are finished
t1.join()
解决方法
从self.window.mainloop()
删除呼叫botGUI.__init__()
,然后您可以:
- 创建
botGUI
的实例:robotGUI = botGUI()
- 创建线程并启动它
- 致电
roboGUI.window.mainloop()
下面是修改后的代码:
#!/usr/bin/env python3
#Imports
import socket,select,errno,sys,queue,time,threading,cv2
from tkinter import *
from tkinter import font
from PIL import Image,ImageTk
#GUI
class botGUI:
def __init__(self):
#Create the Window Object and Setup the Window
self.window = Tk()
self.window.geometry("800x480+0+0")
self.window.overrideredirect(True)
self.window.fullScreenState = False
#Code to Generate Gaphics Here .....
#Call Repeating Status Update Script and Start the Main Loop
self.updateStatus()
#self.window.mainloop()
def updateStatus(self):
#Code to Handle Updating Screen Objects Here ....
print("Update Status Running")
#Set this function to be called again
self.window.after(1000,lambda: self.updateStatus())
def doSomething(self,myStr):
#Code to change something on the screen ...
print(f"Command: {str(myStr)}")
def doSomethingElse(self,myStr):
#Code to change something on the screen ...
print(f"Command: {str(myStr)}")
#Main Task - Since tKinter is running in the main loop,all of the main loop code is moved to here
def main_loop():
#global robotGUI
robotDataReceived = True #This is only for this posting
#Main Loop
while True:
#If Incoming Data from Robot,Get and Process It!
if robotDataReceived:
robotCmdHandler()
#Anti Blocking Delay (Much shorter,set higher for this post)
time.sleep(2)
#Robot Command Handler
def robotCmdHandler():
#global robotGUI
#Code to get a command string and process it goes here .....
cmd = "dosomething" #Temporary for this post
#Handle command
if (cmd == "dosomething"):
print("Processing Command")
robotGUI.doSomething("Do This")
if __name__ == '__main__':
#Create GUI Object
robotGUI = botGUI()
#Create and Start Threads
t1 = threading.Thread(target=main_loop,name='t1')
t1.start()
# start the GUI main loop
robotGUI.window.mainloop()
#Wait until threads are finished
t1.join()
,
您必须在所有类似功能之外定义robotGUI:
robotGUI = None
def main_loop():
global robotGUI
robotDataReceived = True #This is only for this posting
#Main Loop
while True:
#If Incoming Data from Robot,Get and Process It!
if robotDataReceived:
robotCmdHandler()
#Anti Blocking Delay (Much shorter,set higher for this post)
time.sleep(2)