获取非属性变量的属性错误

时间:2015-12-29 11:48:36

标签: python-3.x tkinter

我正在处理一个游戏并得到一个奇怪的错误,其中实例变量未正确保存(据我所知)。当我尝试从RunGame实例访问self.game时会发生这种情况。顺便说一下,这些类是在单独的模块中,并且我没有显示所有代码。游戏运行正常,但是当切换级别时它只会崩溃

class RunGame(object):

    def __init__(self):
        self.makeTk()
        self.currentLevel = 0
        self.bricksLayout = [            #for debugging: a layout of bricks. 3d array with each level
            [
                    [0,1,0,1,1,1,1,1],
                    [0,0,0,0,4,1,1,1],
                    [4,4,4,4,4,4,4,4]
                ],

                [
                    [4,0,0,1,0,1,0,1],
                    [0,0,0,0,0,1,0,1],
                    [4,4,4,4,4,4,4,4]
                ]

            ]

        self.game = GameInstance(self.bricksLayout,self)
        self.game.run = False       #this does nothing for some reason, no error though

    def switchLevel(self):
        print("switching level")
        self.game.run = False       #calling this will give no attribute error

        #self.game.clearCanvas()
        #self.game.canvas.destroy()
        self.currentLevel+=1
        #self.game = Game(self.bricksLayout,self)

    def makeTk(self):
        self.root = Tk()
        self.root.title("PrakeOut")
        self.screen_width = self.root.winfo_screenwidth();  #monitor size
        self.screen_height = self.root.winfo_screenheight();
        #root.wm_attributes("-fullscreen",True)     #this gives fullscreen, but removes the menu
        self.root.resizable(0,0) #cant be resized
        self.root.configure(background="Black")      #bg color of root windw
        #root.geometry("%ix%i+0+0" % (SCREEN_WIDTH, SCREEN_HEIGHT))  #maximizes screen. First two are width and height, other two are x1 and y1
        #root.wm_attributes("-topmost",1);   #places window in foreground   

run = RunGame()

class GameInstance(object):


    def __init__(self, bricksLayout,gameHandler):
        self.bricksLayout = bricksLayout
        self.gameHandler = gameHandler
        self.run = True     #game loop

        self.makeCanvas()

        self.brickList = []    #the list of all da created bricks
        self.makeBricks()
        self.makeBallAndPaddle()

        self.gameLoop()
        self.root.mainloop();    #needs to run main loop otherwise windows doesnt show

它给出了这个错误:

文件“C:\ Users \ Bollen \ Desktop \ python projects \ breakout \ PythonApplication1 \ PythonApplication1 \ GameHandler.py”,第30行,在switchLevel中     self.game.run = False #calling这将不会出现属性错误 AttributeError:'RunGame'对象没有属性'game' 按任意键继续 。 。

1 个答案:

答案 0 :(得分:0)

我们无法使用您的代码重现问题,但代码中存在一个非常明显的逻辑错误。问题是,在使用它们之前,不允许完全创建任何类。

看一下GameInstance:因为你在初始化程序中调用了mainloop,所以在创建根窗口然后销毁之后,该类将永远不会被完全实例化。 。因此,尝试使用此实例的任何其他类都将使用未完全形成的实例。

同样,使用GameRunner您正在创建GameInstance的实例。由于GameInstance调用了mainloop,因此在GameRunner创建之前无法完成GameInstance对象的创建,并且GameInstance将无法完成窗户被毁了。

第一步是从mainloop删除对GameInstance.__init__的来电。相反,将其移动到GameRunner完全创建后可以调用的方法中。

您还应该将两个对象的创建分为两个步骤。你的主要逻辑看起来如下所示。我不确定你是先创建跑步者还是先打游戏,但是根据你如何定义类,这两种方式都是可以接受的。

game = GameInstance(...)
runner = GameRunner(..., game)
runner.run()  

在上面,runner.run()看起来像这样:

class GameRunner(...):
    def run(self):
        self.game.run()

...而game.run看起来像这样:

class GameInstance(...):
    def run(self):
        self.gameLoop()
        self.root.mainloop()