NameError:name' self'从类中调用方法时没有定义Python

时间:2017-11-20 05:02:36

标签: python python-3.x tkinter

我正在尝试使用Tkinter库在python中制作类似破砖机的游戏。我有一个运行良好的代码的先前版本,但由于缩进错误,所有函数都在__init__。当我更正此错误然后添加功能以使其成为可玩的游戏时,我的主动画循环停止工作。我阅读了其他帖子,显示这是一个间距错误,并验证这不是使用python -tt。更新:self.moveBall()已移至__init__,但moveBall()仍未运行。

from tkinter import *


class Application(Frame):

    def __init__(self):

# Constructing the Screen

    root = Tk()
    Frame.__init__(self)
    self.canvas = Canvas(root, width=800, height=400)

# Label

    self.v = StringVar()
    self.l = 5
    self.label = Label(root, textvariable=self.v, font=('Courier',
                       20), bg='white', width=50)
    self.v.set('Lives: ' + str(self.l))
    self.label.grid()
    self.canvas.grid()

# Ball

    self.canvas.create_oval(
        2,
        2,
        22,
        22,
        fill='red',
        tags='ball',
        )

# Paddle

    self.canvas.create_rectangle(
        360,
        380,
        440,
        400,
        fill='black',
        tag='paddle',
        )

# Keybindings

    self.canvas.focus_set()
    self.canvas.bind('<Left>', self.paddleLeft)
    self.canvas.bind('a', self.paddleLeft)
    self.canvas.bind('<Button-1>', self.paddleLeft)
    self.canvas.bind('<Right>', self.paddleRight)
    self.canvas.bind('d', self.paddleRight)
    self.canvas.bind('<Button-3>', self.paddleRight)

# Logic

    self.horizontal_direction = 'east'
    self.vertical_direcction = 'south'
    self.moveBall()

    def collide(self):
        (x1, y1, x2, y2) = self.canvas.coords('ball')
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if x2 >= 800:
            self.horizontal_direction = 'west'
        if x1 <= 0:
            self.horizontal_direction = 'east'
        if y1 <= 0:
            self.vertical_direcction = 'south'
        if y2 >= 400:
            self.l -= 1
            self.v.set('Lives: ' + str(self.l))
            self.vertical_direcction = 'north'
        if y2 >= py1:
            if x1 in range(int(px1), int(px2)) or x2 in range(int(px1),
                    int(px2)):
                self.vertical_direcction = 'north'

    def moveBall(self):
        while True:
            if self.horizontal_direction == 'east':
                self.canvas.move('ball', 2, 0)
            else:
                self.canvas.move('ball', -2, 0)
            if self.vertical_direcction == 'south':
                self.canvas.move('ball', 0, 2)
            else:
                self.canvas.move('ball', 0, -2)
                self.canvas.after(15)
                self.collide()
                self.canvas.update()

    def paddleLeft(self, event):
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if px1 >= 0:
            self.canvas.move('paddle', -5, 0)
            self.canvas.after(15)
            self.canvas.update()

    def paddleRight(self, event):
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if px2 <= 800:
            self.canvas.move('paddle', 5, 0)
            self.canvas.after(15)
            self.canvas.update()




def main():
   app = Application()
   app.mainloop()


main()

这是控制台输出:

    Traceback (most recent call last):
    File "C:\Users\daeda\Downloads\main.py", line 4, in <module>
    class Application(Frame):
    File "C:\Users\daeda\Downloads\main.py", line 107, in Application
    self.moveBall()
    NameError: name 'self' is not defined

2 个答案:

答案 0 :(得分:1)

据我所知,当您尝试使用self从类外部调用方法时,通常会发生此类错误。

我相信你的错误在于

self.moveball()

在这里,您尝试从课程范围之外的moveball()拨打self

我希望它能帮助你克服这个问题。

答案 1 :(得分:0)

我做了这样的事情:

它使用self.root,因此我可以在moveBall中使用self.root.after(15, moveBall)并在15ms后再次运行moveBall并且我不需要while True。我也不需要canvas.after(15)canvas.update()

我从Frame删除了class Application(Frame):,因为您将所有小部件直接添加到root,并且从未使用此Frame。在小部件中,您必须使用self代替root向此Frame添加小部件,而Frame必须使用master=root将小部件添加到主窗口

from tkinter import *


class Application():

    def __init__(self):

        # Constructing the Screen

        self.root = Tk()
        self.canvas = Canvas(self.root, width=800, height=400)

        # Label

        self.v = StringVar()
        self.l = 5
        self.label = Label(self.root, textvariable=self.v, font=('Courier',
                           20), bg='white', width=50)
        self.v.set('Lives: ' + str(self.l))
        self.label.grid()
        self.canvas.grid()

        # Ball

        self.canvas.create_oval(
            2,
            2,
            22,
            22,
            fill='red',
            tags='ball',
            )

        # Paddle

        self.canvas.create_rectangle(
            360,
            380,
            440,
            400,
            fill='black',
            tag='paddle',
            )

        # Keybindings

        self.canvas.focus_set()
        self.canvas.bind('<Left>', self.paddleLeft)
        self.canvas.bind('a', self.paddleLeft)
        self.canvas.bind('<Button-1>', self.paddleLeft)
        self.canvas.bind('<Right>', self.paddleRight)
        self.canvas.bind('d', self.paddleRight)
        self.canvas.bind('<Button-3>', self.paddleRight)

        # Logic

        self.horizontal_direction = 'east'
        self.vertical_direcction = 'south'

        # run after 250ms so mainloop has time to start
        self.root.after(250, self.moveBall)

        self.root.mainloop()

    def collide(self):
        (x1, y1, x2, y2) = self.canvas.coords('ball')
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if x2 >= 800:
            self.horizontal_direction = 'west'
        if x1 <= 0:
            self.horizontal_direction = 'east'
        if y1 <= 0:
            self.vertical_direcction = 'south'
        if y2 >= 400:
            self.l -= 1
            self.v.set('Lives: ' + str(self.l))
            self.vertical_direcction = 'north'
        if y2 >= py1:
            if x1 in range(int(px1), int(px2)) or x2 in range(int(px1),
                    int(px2)):
                self.vertical_direcction = 'north'

    def moveBall(self):

        if self.horizontal_direction == 'east':
            self.canvas.move('ball', 2, 0)
        else:
            self.canvas.move('ball', -2, 0)
        if self.vertical_direcction == 'south':
            self.canvas.move('ball', 0, 2)
        else:
            self.canvas.move('ball', 0, -2)
            self.collide()

        # run again after 15ms - so I don't need `while True`
        self.root.after(15, self.moveBall)

    def paddleLeft(self, event):
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if px1 >= 0:
            self.canvas.move('paddle', -5, 0)

    def paddleRight(self, event):
        (px1, py1, px2, py2) = self.canvas.coords('paddle')
        if px2 <= 800:
            self.canvas.move('paddle', 5, 0)

# --- start ---

Application()