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

时间:2018-08-13 19:31:10

标签: python object tkinter global

我试图了解Python类如何工作以能够遵循OOP的四个支柱。

我正在尝试设置一个Controller类,该类将设置一些UI类并响应输入。当前,Controller类初始化一个框架,该框架初始化一些Button。控制器将click(x,y)函数传递给UI类以监听点击。该部分目前正在运行,但我似乎无法弄清楚控制器类如何访问其子类以对UI进行更改。

这是我到目前为止获得的代码。我的问题是Controller中的Click(x,y)函数似乎找不到在 main 中创建的“游戏”对象。

Controller.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")

GameFrame.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

GameButtons.py:

{{1}}

单击按钮正确地从click(x,y)函数输出行/列,但随后给我一个NameError:尝试运行game.changeColor(x,y)时未定义名称“ game”

将非常感谢您为解决此问题提供的任何帮助,或者对我为什么要实现的目标一开始是一个坏主意的任何解释。

1 个答案:

答案 0 :(得分:1)

问题在于,您永远不会给GameFrame一个完成初始化的机会,因为mainloop在窗口被销毁之前不会返回。因此,由于初始化从未完成,game没有正确初始化。

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

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

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

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()