尝试设置全局对象,但在尝试从另一个文件访问子类时未定义获取 NameError 对象

Trying to set up global object, but getting NameError object is not defined when trying to access subclass from another file

我试图了解 Python classes 如何工作以遵循 OOP 的四大支柱。

我正在尝试设置一个控制器 class,它将设置一些 UI classes 并响应输入。当前控制器 class 初始化一个框架,该框架初始化一些按钮。控制器将 click(x,y) 函数传递给 UI classes 以监听点击。该部分目前正在工作,但我似乎无法弄清楚控制器 class 如何访问它的子 class 以对 UI.

进行更改

这是我目前得到的代码。我的问题是控制器中的 Click(x,y) 函数似乎无法找到在 main.

中创建的 "game" 对象

Controller.py:

from GameFrame import GameFrame
global game

def click(x, y):
    global game
    print("%s %s" %(x,y))
    game.changeColor(x, y)

if __name__ == '__main__':
    global game
    game = GameFrame("title", click) 
    pass

GameFrame.py:

from GameButtons import GameButtons
from tkinter import *
class GameFrame(object):
    global gameButtons

    def __init__(self, params, click):
        frame = Tk()
        gameButtons= GameButtons(frame,click)
        frame.mainloop()        

    def changeColor(self, x, y):
        gameButtons.buttons[x][y].configure(bg = "green")

GameButtons.py:

from tkinter import *
class GameButtons(object):

    global buttons
    buttons = [[0 for x in range(8)]for x in range(8)]

    def __init__(self, frame, click):
        for x in range(8):
            for y in range(8):
                b = Button(frame, text = " x ", command = lambda row = x, col = y: click(row, col)) 
                b.grid(row = x, column = y)
                global buttons
                buttons[x][y] = b

单击按钮正确地从 click(x,y) 函数输出 row/column 但随后给我一个 NameError: name 'game' is not defined when trying to 运行 game.changeColor(x,y)

非常感谢任何解决这个问题的帮助,或者任何解释为什么我试图实现的首先是一个坏主意。

问题是你永远不会给 GameFrame 一个完成初始化的机会,因为 mainloop 不会 return 直到 window 被销毁。因此,由于初始化永远不会完成,因此 game 未正确初始化。

简单的解决方法是将对 mainloop 的调用移到初始化函数之外,以便可以正确初始化对象。您的主要代码应如下所示:

if __name__ == '__main__':
    game = GameFrame("title", click)
    game.start()

然后,你需要在GameFrame中定义一个start方法。这将要求您持有对根 window 的引用。我会这样写:

class GameFrame(object):
    def __init__(self, params, click):
        self.root = Tk()
        gameButtons = GameButtons(self.root, click)

    def start(self):
        self.root.mainloop()

注意:如果你的目标是真正的面向对象,你需要移除对全局变量的依赖。

这是您重写的代码,因此它不使用全局变量,game 除外,它本质上是全局变量:

from tkinter import *

class GameButtons(object):
    def __init__(self, frame, click):
        self.buttons = [[None for x in range(8)] for x in range(8)]
        for x in range(8):
            for y in range(8):
                b = Button(frame, text = " x ", command = lambda row = x, col = y: click(row, col)) 
                self.buttons[x][y] = b
                b.grid(row = x, column = y)

class GameFrame(object):
    def __init__(self, params, click):
        self.root = Tk()
        self.gameButtons= GameButtons(self.root,click)

    def changeColor(self, x, y):
        self.gameButtons.buttons[x][y].configure(bg = "green")

    def start(self):
        self.root.mainloop()

def click(x, y):
    print("%s %s" %(x,y))
    game.changeColor(x, y)

if __name__ == '__main__':
    game = GameFrame("title", click) 
    game.start()